Search in sources :

Example 6 with Cause

use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.

the class ServerLevelMixin method save.

/**
 * @author zidane - December 17th, 2020 - Minecraft 1.16.4
 * @reason Honor our serialization behavior in performing saves
 */
@Overwrite
public void save(@Nullable final ProgressListener progress, final boolean flush, final boolean skipSave) {
    final Cause currentCause = Sponge.server().causeStackManager().currentCause();
    if (Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPre(currentCause, ((ServerWorld) this)))) {
        // cancelled save
        return;
    }
    final PrimaryLevelData levelData = (PrimaryLevelData) this.shadow$getLevelData();
    final ServerChunkCache chunkProvider = ((ServerLevel) (Object) this).getChunkSource();
    if (!skipSave) {
        final SerializationBehavior behavior = ((PrimaryLevelDataBridge) levelData).bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC);
        if (progress != null) {
            progress.progressStartNoAbort(new TranslatableComponent("menu.savingLevel"));
        }
        // We always save the metadata unless it is NONE
        if (behavior != SerializationBehavior.NONE) {
            this.shadow$saveLevelData();
            // Sponge Start - We do per-world WorldInfo/WorldBorders/BossBars
            levelData.setWorldBorder(this.getWorldBorder().createSettings());
            levelData.setCustomBossEvents(((ServerLevelBridge) this).bridge$getBossBarManager().save());
            ((ServerLevelBridge) this).bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), (PrimaryLevelData) this.shadow$getLevelData(), this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null);
        // Sponge End
        }
        if (progress != null) {
            progress.progressStage(new TranslatableComponent("menu.savingChunks"));
        }
        final boolean canAutomaticallySave = !this.impl$isManualSave && behavior == SerializationBehavior.AUTOMATIC;
        final boolean canManuallySave = this.impl$isManualSave && behavior == SerializationBehavior.MANUAL;
        if (canAutomaticallySave || canManuallySave) {
            chunkProvider.save(flush);
        }
        Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPost(currentCause, ((ServerWorld) this)));
    }
    this.impl$isManualSave = false;
}
Also used : PrimaryLevelData(net.minecraft.world.level.storage.PrimaryLevelData) ServerLevel(net.minecraft.server.level.ServerLevel) TranslatableComponent(net.minecraft.network.chat.TranslatableComponent) Cause(org.spongepowered.api.event.Cause) SerializationBehavior(org.spongepowered.api.world.SerializationBehavior) ServerChunkCache(net.minecraft.server.level.ServerChunkCache) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge) PlatformServerLevelBridge(org.spongepowered.common.bridge.world.level.PlatformServerLevelBridge) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 7 with Cause

use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.

the class ContainerBasedTransaction method generateEvent.

@Override
public Optional<ClickContainerEvent> generateEvent(final PhaseContext<@NonNull ?> context, @Nullable final GameTransaction<@NonNull ?> parent, final ImmutableList<GameTransaction<ClickContainerEvent>> gameTransactions, final Cause currentCause) {
    final ImmutableList<ContainerBasedTransaction> containerBasedTransactions = gameTransactions.stream().filter(tx -> tx instanceof ContainerBasedTransaction).map(tx -> (ContainerBasedTransaction) tx).filter(tx -> !tx.used).collect(ImmutableList.toImmutableList());
    if (containerBasedTransactions.stream().map(c -> c.isContainerEventAllowed(context)).filter(b -> !b).findAny().orElse(false)) {
        SpongeCommon.logger().warn("No event will be fired for existing ContainerBasedTransactions: {}", containerBasedTransactions.size());
        return Optional.empty();
    }
    if (!((TrackedContainerBridge) this.menu).bridge$capturePossible()) {
    // if (ContainerBasedTransaction.containersFailedCapture.add(this.menu.getClass())) {
    // SpongeCommon.logger()
    // .warn("Changes in modded Container were not captured. Inventory events will not fire for this. Container: " + this.menu.getClass());
    // }
    }
    final List<Entity> entities = containerBasedTransactions.stream().map(ContainerBasedTransaction::getEntitiesSpawned).flatMap(List::stream).collect(Collectors.toList());
    final List<SlotTransaction> slotTransactions = containerBasedTransactions.stream().map(ContainerBasedTransaction::getSlotTransactions).flatMap(List::stream).collect(Collectors.toList());
    if (this.craftingInventory != null) {
        // Event with Preview transaction on crafting inventory?
        Slot slot = this.craftingInventory.result();
        @Nullable final SlotTransaction preview = this.findPreviewTransaction(this.craftingInventory.result(), slotTransactions);
        final ItemStackSnapshot previewItem = ItemStackUtil.snapshotOf(this.craftingInventory.peek());
        if (preview != null) {
            slot = preview.slot();
            // Check if preview transaction is correct
            if (!preview.defaultReplacement().equals(previewItem)) {
                slotTransactions.remove(preview);
                slotTransactions.add(new SlotTransaction(slot, preview.original(), previewItem));
            }
        } else if (!previewItem.isEmpty()) {
            slotTransactions.add(new SlotTransaction(slot, previewItem, previewItem));
        }
    }
    for (final ContainerBasedTransaction transaction : containerBasedTransactions) {
        transaction.used = true;
    }
    final Optional<ClickContainerEvent> event = containerBasedTransactions.stream().map(t -> t.createInventoryEvent(slotTransactions, entities, context, currentCause)).filter(Optional::isPresent).map(Optional::get).findFirst();
    if (!event.isPresent() && !slotTransactions.isEmpty()) {
        SpongeCommon.logger().warn("Logged slot transactions without event! {} {}", gameTransactions.size(), this.menu.getClass().getName(), new Exception(""));
        for (final SlotTransaction slotTransaction : slotTransactions) {
            SpongeCommon.logger().warn(slotTransaction);
        }
    }
    return event;
}
Also used : NonNull(org.checkerframework.checker.nullness.qual.NonNull) ClientboundContainerSetSlotPacket(net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket) AbstractContainerMenu(net.minecraft.world.inventory.AbstractContainerMenu) SpawnEntityTransaction(org.spongepowered.common.event.tracking.context.transaction.world.SpawnEntityTransaction) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) ClickContainerEvent(org.spongepowered.api.event.item.inventory.container.ClickContainerEvent) TransactionTypes(org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes) ArrayList(java.util.ArrayList) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) ServerPlayer(net.minecraft.server.level.ServerPlayer) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) TrackedContainerBridge(org.spongepowered.common.bridge.world.inventory.container.TrackedContainerBridge) ImmutableList(com.google.common.collect.ImmutableList) ItemStackUtil(org.spongepowered.common.item.util.ItemStackUtil) CraftItemEvent(org.spongepowered.api.event.item.inventory.CraftItemEvent) BiConsumer(java.util.function.BiConsumer) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LinkedList(java.util.LinkedList) RecipeType(net.minecraft.world.item.crafting.RecipeType) Nullable(org.checkerframework.checker.nullness.qual.Nullable) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) Set(java.util.Set) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) ContainerUtil(org.spongepowered.common.inventory.util.ContainerUtil) Slot(org.spongepowered.api.item.inventory.Slot) SpongeCommon(org.spongepowered.common.SpongeCommon) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) CraftingOutput(org.spongepowered.api.item.inventory.crafting.CraftingOutput) Entity(org.spongepowered.api.entity.Entity) Collectors(java.util.stream.Collectors) Player(net.minecraft.world.entity.player.Player) Cause(org.spongepowered.api.event.Cause) EntityUtil(org.spongepowered.common.entity.EntityUtil) List(java.util.List) CraftingContainer(net.minecraft.world.inventory.CraftingContainer) GameTransaction(org.spongepowered.common.event.tracking.context.transaction.GameTransaction) Container(org.spongepowered.api.item.inventory.Container) ReferenceOpenHashSet(it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet) PhaseContext(org.spongepowered.common.event.tracking.PhaseContext) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) CraftingRecipe(org.spongepowered.api.item.recipe.crafting.CraftingRecipe) PacketPhaseUtil(org.spongepowered.common.event.tracking.phase.packet.PacketPhaseUtil) Optional(java.util.Optional) ItemStack(net.minecraft.world.item.ItemStack) Collections(java.util.Collections) Entity(org.spongepowered.api.entity.Entity) Optional(java.util.Optional) ClickContainerEvent(org.spongepowered.api.event.item.inventory.container.ClickContainerEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Slot(org.spongepowered.api.item.inventory.Slot) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 8 with Cause

use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.

the class ClickCreativeMenuTransaction method createInventoryEvent.

@Override
Optional<ClickContainerEvent> createInventoryEvent(final List<SlotTransaction> slotTransactions, final List<Entity> entities, final PhaseContext<@NonNull ?> context, final Cause cause) {
    if (slotTransactions.isEmpty() && this.slotNum >= 0 && this.slot != null) {
        // No SlotTransaction was captured. So we add the clicked slot as a transaction with the creative stack
        final ItemStackSnapshot item = this.slot.peek().createSnapshot();
        slotTransactions.add(new SlotTransaction(this.slot, item, this.creativeStack));
    }
    // Creative doesn't inform server of cursor status so there is no way of knowing what the final stack is
    final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(this.originalCursor, ItemStackSnapshot.empty());
    if (entities.isEmpty()) {
        return Optional.of(SpongeEventFactory.createClickContainerEventCreativeSet(cause, (Container) this.menu, cursorTransaction, Optional.ofNullable(this.slot), slotTransactions));
    }
    final Cause causeWithSpawnType = Cause.builder().from(cause).build(EventContext.builder().from(cause.context()).add(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM.get()).build());
    return Optional.of(SpongeEventFactory.createClickContainerEventCreativeDrop(causeWithSpawnType, (Container) this.menu, cursorTransaction, this.creativeStack, entities, Optional.ofNullable(this.slot), slotTransactions));
}
Also used : Container(org.spongepowered.api.item.inventory.Container) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) Cause(org.spongepowered.api.event.Cause) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction)

Example 9 with Cause

use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.

the class SpongeInventoryMenu method onClick.

public boolean onClick(int slotId, int dragType, ClickType clickTypeIn, Player player, Container container) {
    try (CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(player);
        Cause cause = frame.currentCause();
        if (clickTypeIn == ClickType.QUICK_CRAFT) {
            return this.onClickDrag(cause, slotId, dragType, container);
        }
        Optional<org.spongepowered.api.item.inventory.Slot> slot = container.slot(slotId);
        if (slot.isPresent()) {
            switch(clickTypeIn) {
                case SWAP:
                    if (dragType >= 0 && dragType < 9) {
                        Optional<org.spongepowered.api.item.inventory.Slot> slot2 = container.slot(dragType);
                        if (slot2.isPresent() && this.keySwapHandler != null) {
                            return this.keySwapHandler.handle(cause, container, slot.get(), slotId, ClickTypes.KEY_SWAP.get(), slot2.get());
                        }
                    }
                    break;
                case CLONE:
                    if (this.slotClickHandler != null) {
                        return this.slotClickHandler.handle(cause, container, slot.get(), slotId, ClickTypes.CLICK_MIDDLE.get());
                    }
                    break;
                case PICKUP_ALL:
                    if (this.slotClickHandler != null) {
                        return this.slotClickHandler.handle(cause, container, slot.get(), slotId, ClickTypes.DOUBLE_CLICK.get());
                    }
                    break;
                default:
                    if (this.slotClickHandler != null) {
                        if (dragType == 0) {
                            return this.onClickLeft(cause, this.slotClickHandler, clickTypeIn, container, slotId, slot.get());
                        } else if (dragType == 1) {
                            return this.onClickRight(cause, this.slotClickHandler, clickTypeIn, container, slotId, slot.get());
                        }
                    // else unknown drag-type
                    }
            }
            return true;
        }
        // else no slot present
        switch(clickTypeIn) {
            case PICKUP:
                if (slotId == -999 && this.clickHandler != null) {
                    if (dragType == 0) {
                        return this.clickHandler.handle(cause, container, ClickTypes.CLICK_LEFT_OUTSIDE.get());
                    } else if (dragType == 1) {
                        return this.clickHandler.handle(cause, container, ClickTypes.CLICK_RIGHT_OUTSIDE.get());
                    }
                }
                // else unknown slotId/drag-type
                break;
            case THROW:
                if (slotId == -999) {
                // TODO check packets - does THROW with slotid -999 exist or is this actually PICKUP?
                // its supposed to be l/r-click with nothing in hand
                // TODO check if those exist
                // /**
                // * Throwing one item on the cursor by clicking outside the inventory window.
                // */
                // public static final org.spongepowered.api.item.inventory.menu.ClickType
                // CLICK_THROW_ONE = DummyObjectProvider.createFor(org.spongepowered.api.item.inventory.menu.ClickType.class, "click_throw_one");
                // /**
                // * Throwing all items on the cursor by clicking outside the inventory window.
                // */
                // public static final org.spongepowered.api.item.inventory.menu.ClickType
                // CLICK_THROW_ALL = DummyObjectProvider.createFor(org.spongepowered.api.item.inventory.menu.ClickType.class, "click_throw_all");
                }
                // else unknown slotId/drag-type
                break;
        }
        return true;
    }
}
Also used : CauseStackManager(org.spongepowered.api.event.CauseStackManager) Cause(org.spongepowered.api.event.Cause) Slot(net.minecraft.world.inventory.Slot)

Example 10 with Cause

use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.

the class AdvancementProgressMixin method impl$revokeCriterion.

private boolean impl$revokeCriterion(String rawCriterion) {
    final net.minecraft.advancements.CriterionProgress criterionProgress = this.criteria.get(rawCriterion);
    if (criterionProgress == null || !criterionProgress.isDone()) {
        return false;
    }
    if (SpongeScoreCriterion.BYPASS_EVENT) {
        criterionProgress.revoke();
        return true;
    }
    final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
    final ServerPlayer player = ((PlayerAdvancementsBridge) this.impl$playerAdvancements).bridge$getPlayer();
    final CriterionProgress progress = (CriterionProgress) criterionProgress;
    final AdvancementCriterion criterion = progress.criterion();
    final CriterionBridge criterionBridge = (CriterionBridge) criterion;
    // The score criterion needs special care
    final SpongeScoreCriterion scoreCriterion = criterionBridge.bridge$getScoreCriterion();
    final CriterionEvent event;
    final Advancement advancement = ((org.spongepowered.api.advancement.AdvancementProgress) this).advancement();
    if (scoreCriterion != null) {
        final SpongeScoreCriterionProgress scoreProgress = (SpongeScoreCriterionProgress) this.impl$progressMap.get(scoreCriterion.name());
        final int lastScore = scoreProgress.score();
        final int score = lastScore + 1;
        if (lastScore == scoreCriterion.goal()) {
            event = SpongeEventFactory.createCriterionEventScoreRevoke(cause, advancement, scoreCriterion, player, lastScore, score);
        } else if (score == scoreCriterion.goal()) {
            event = SpongeEventFactory.createCriterionEventScoreGrant(cause, advancement, scoreCriterion, player, Instant.now(), lastScore, score);
        } else {
            event = SpongeEventFactory.createCriterionEventScoreChange(cause, advancement, scoreCriterion, player, lastScore, score);
        }
    } else {
        event = SpongeEventFactory.createCriterionEventRevoke(cause, advancement, criterion, player);
    }
    if (SpongeCommon.post(event)) {
        return false;
    }
    criterionProgress.revoke();
    return true;
}
Also used : AdvancementProgress(net.minecraft.advancements.AdvancementProgress) CriterionEvent(org.spongepowered.api.event.advancement.CriterionEvent) PlayerAdvancementsBridge(org.spongepowered.common.bridge.server.PlayerAdvancementsBridge) AdvancementCriterion(org.spongepowered.api.advancement.criteria.AdvancementCriterion) SpongeScoreCriterion(org.spongepowered.common.advancement.criterion.SpongeScoreCriterion) SpongeScoreCriterionProgress(org.spongepowered.common.advancement.criterion.SpongeScoreCriterionProgress) Cause(org.spongepowered.api.event.Cause) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) Advancement(org.spongepowered.api.advancement.Advancement) SpongeAndCriterionProgress(org.spongepowered.common.advancement.criterion.SpongeAndCriterionProgress) SpongeOrCriterionProgress(org.spongepowered.common.advancement.criterion.SpongeOrCriterionProgress) SpongeScoreCriterionProgress(org.spongepowered.common.advancement.criterion.SpongeScoreCriterionProgress) ImplementationBackedCriterionProgress(org.spongepowered.common.advancement.criterion.ImplementationBackedCriterionProgress) CriterionProgress(org.spongepowered.api.advancement.criteria.CriterionProgress) CriterionBridge(org.spongepowered.common.bridge.advancements.CriterionBridge)

Aggregations

Cause (org.spongepowered.api.event.Cause)55 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)19 ServerWorld (org.spongepowered.api.world.server.ServerWorld)18 Inject (org.spongepowered.asm.mixin.injection.Inject)18 ArrayList (java.util.ArrayList)16 BlockPos (net.minecraft.core.BlockPos)15 CauseStackManager (org.spongepowered.api.event.CauseStackManager)15 List (java.util.List)13 Optional (java.util.Optional)12 ServerLocation (org.spongepowered.api.world.server.ServerLocation)12 Entity (net.minecraft.world.entity.Entity)11 Player (net.minecraft.world.entity.player.Player)11 Collections (java.util.Collections)10 Collection (java.util.Collection)9 Map (java.util.Map)9 LivingEntity (net.minecraft.world.entity.LivingEntity)9 EventContext (org.spongepowered.api.event.EventContext)9 HashMap (java.util.HashMap)8 BlockState (net.minecraft.world.level.block.state.BlockState)8 ServerPlayer (org.spongepowered.api.entity.living.player.server.ServerPlayer)8