Search in sources :

Example 31 with SpawnEntityEvent

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

the class ExplosionState method unwind.

@Override
public void unwind(ExplosionContext context) {
    final Explosion explosion = context.getSpongeExplosion();
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        context.addNotifierAndOwnerToCauseStack();
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.TNT_IGNITE);
        Sponge.getCauseStackManager().pushCause(explosion);
        context.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> processBlockCaptures(blocks, explosion, context));
        context.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
            final User user = context.getNotifier().orElseGet(() -> context.getOwner().orElse(null));
            final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
            SpongeImpl.postEvent(event);
            if (!event.isCancelled()) {
                for (Entity entity : event.getEntities()) {
                    if (user != null) {
                        EntityUtil.toMixin(entity).setCreator(user.getUniqueId());
                    }
                    EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
                }
            }
        });
    }
}
Also used : Entity(org.spongepowered.api.entity.Entity) Explosion(org.spongepowered.api.world.explosion.Explosion) User(org.spongepowered.api.entity.living.player.User) CauseStackManager(org.spongepowered.api.event.CauseStackManager) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent)

Example 32 with SpawnEntityEvent

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

the class GeneralState method spawnEntityOrCapture.

/**
 * A duplicate of {@link IPhaseState#spawnEntityOrCapture(PhaseContext, Entity, int, int)}
 * such that the general states will not know what to do for entity spawns. Eventually, this is going to be centralized
 * so that it's not always delegated between the phases and phase states.
 *
 * Basically, for this method, this is included only for the {@link GeneralPhase.State#COMPLETE}, all other
 * will capture or spawn appropriately. In the case of explosions for example, the entities must be mapped
 * according to the blocks broken so that the blocks themselves can be cancelled and the entities spawned
 * are dropped from the game entirely before throwing additional events.
 *
 * @param context
 * @param entity
 * @param chunkX
 * @param chunkZ
 * @return
 */
@Override
public boolean spawnEntityOrCapture(G context, Entity entity, int chunkX, int chunkZ) {
    final User user = context.getNotifier().orElseGet(() -> context.getOwner().orElse(null));
    if (user != null) {
        entity.setCreator(user.getUniqueId());
    }
    final ArrayList<Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
    SpongeImpl.postEvent(event);
    if (!event.isCancelled() && event.getEntities().size() > 0) {
        for (Entity item : event.getEntities()) {
            ((IMixinWorldServer) item.getWorld()).forceSpawnEntity(item);
        }
        return true;
    }
    return false;
}
Also used : Entity(org.spongepowered.api.entity.Entity) User(org.spongepowered.api.entity.living.player.User) ArrayList(java.util.ArrayList) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent)

Example 33 with SpawnEntityEvent

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

the class BasicInventoryPacketState method unwind.

@Override
public void unwind(InventoryPacketContext context) {
    final EntityPlayerMP player = context.getPacketPlayer();
    // The server will disable the player's crafting after receiving a
    // client packet
    // that did not pass validation (server click item != packet click item)
    // The server then sends a SPacketConfirmTransaction and waits for a
    // CPacketConfirmTransaction to re-enable crafting confirming that the
    // client
    // acknowledged the denied transaction.
    // To detect when this happens, we turn off capturing so we can avoid
    // firing
    // invalid events.
    // See MixinNetHandlerPlayServer processClickWindow redirect for rest of
    // fix.
    // --bloodmc
    final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
    if (!mixinContainer.capturingInventory()) {
        mixinContainer.getCapturedTransactions().clear();
        return;
    }
    // TODO clear this shit out of the context
    final CPacketClickWindow packetIn = context.getPacket();
    final ItemStackSnapshot lastCursor = context.getCursor();
    final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(player.inventory.getItemStack());
    final Transaction<ItemStackSnapshot> transaction = new Transaction<>(lastCursor, newCursor);
    final net.minecraft.inventory.Container openContainer = player.openContainer;
    final List<SlotTransaction> slotTransactions = mixinContainer.getCapturedTransactions();
    final int usedButton = packetIn.getUsedButton();
    final List<Entity> capturedItems = new ArrayList<>();
    for (EntityItem entityItem : context.getCapturedItems()) {
        capturedItems.add(EntityUtil.fromNative(entityItem));
    }
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(openContainer);
        Sponge.getCauseStackManager().pushCause(player);
        final ClickInventoryEvent inventoryEvent;
        inventoryEvent = this.createInventoryEvent(player, ContainerUtil.fromNative(openContainer), transaction, Lists.newArrayList(slotTransactions), capturedItems, usedButton);
        // If this happens and we captured no entities, avoid firing events
        if (mixinContainer.getCapturedTransactions().isEmpty() && capturedItems.isEmpty() && transaction.getOriginal().equals(transaction.getFinal())) {
            mixinContainer.setCaptureInventory(false);
            return;
        }
        if (inventoryEvent != null) {
            // Don't fire inventory drop events when there are no entities
            if (inventoryEvent instanceof AffectEntityEvent && ((AffectEntityEvent) inventoryEvent).getEntities().isEmpty()) {
                slotTransactions.clear();
                mixinContainer.setCaptureInventory(false);
                return;
            }
            // packet has everything we want.
            if (!(inventoryEvent instanceof ClickInventoryEvent.Drag)) {
                PacketPhaseUtil.validateCapturedTransactions(packetIn.getSlotId(), openContainer, inventoryEvent.getTransactions());
            }
            SpongeImpl.postEvent(inventoryEvent);
            if (inventoryEvent.isCancelled() || PacketPhaseUtil.allTransactionsInvalid(inventoryEvent.getTransactions())) {
                if (inventoryEvent instanceof ClickInventoryEvent.Drop) {
                    capturedItems.clear();
                }
                // Restore cursor
                if (inventoryEvent.isCancelled() || !inventoryEvent.getCursorTransaction().isValid()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
                } else if (inventoryEvent.getCursorTransaction().getCustom().isPresent()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getFinal());
                }
                // Restore target slots
                PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), true);
            } else {
                PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), false);
                // Handle cursor
                if (!inventoryEvent.getCursorTransaction().isValid()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
                } else if (inventoryEvent.getCursorTransaction().getCustom().isPresent()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getFinal());
                } else if (inventoryEvent instanceof ClickInventoryEvent.Drag) {
                    int increment;
                    increment = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getFinal().getQuantity()).sum();
                    final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
                    cursor.setQuantity(cursor.getQuantity() + increment);
                    PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
                } else if (inventoryEvent instanceof ClickInventoryEvent.Double && !(inventoryEvent instanceof ClickInventoryEvent.Shift)) {
                    int decrement;
                    decrement = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getOriginal().getQuantity()).sum();
                    final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
                    cursor.setQuantity(cursor.getQuantity() - decrement);
                    PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
                }
                if (inventoryEvent instanceof SpawnEntityEvent) {
                    processSpawnedEntities(player, (SpawnEntityEvent) inventoryEvent);
                } else if (!context.getCapturedEntitySupplier().isEmpty()) {
                    SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), context.getCapturedEntities());
                    SpongeImpl.postEvent(spawnEntityEvent);
                    if (!spawnEntityEvent.isCancelled()) {
                        processSpawnedEntities(player, spawnEntityEvent);
                    }
                }
            }
        }
    }
    slotTransactions.clear();
    mixinContainer.setCaptureInventory(false);
}
Also used : SpongeImpl(org.spongepowered.common.SpongeImpl) CPacketClickWindow(net.minecraft.network.play.client.CPacketClickWindow) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStackUtil(org.spongepowered.common.item.inventory.util.ItemStackUtil) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) ArrayList(java.util.ArrayList) ContainerUtil(org.spongepowered.common.item.inventory.util.ContainerUtil) ItemStack(org.spongepowered.api.item.inventory.ItemStack) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Lists(com.google.common.collect.Lists) AffectEntityEvent(org.spongepowered.api.event.entity.AffectEntityEvent) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) Transaction(org.spongepowered.api.data.Transaction) Nullable(javax.annotation.Nullable) EntityItem(net.minecraft.entity.item.EntityItem) Packet(net.minecraft.network.Packet) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) Sponge(org.spongepowered.api.Sponge) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) Entity(org.spongepowered.api.entity.Entity) EntityUtil(org.spongepowered.common.entity.EntityUtil) List(java.util.List) Container(org.spongepowered.api.item.inventory.Container) Entity(org.spongepowered.api.entity.Entity) CPacketClickWindow(net.minecraft.network.play.client.CPacketClickWindow) ArrayList(java.util.ArrayList) CauseStackManager(org.spongepowered.api.event.CauseStackManager) EntityItem(net.minecraft.entity.item.EntityItem) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) AffectEntityEvent(org.spongepowered.api.event.entity.AffectEntityEvent) ItemStack(org.spongepowered.api.item.inventory.ItemStack)

Example 34 with SpawnEntityEvent

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

the class InteractEntityPacketState method unwind.

@Override
public void unwind(BasicPacketContext phaseContext) {
    final EntityPlayerMP player = phaseContext.getPacketPlayer();
    final CPacketUseEntity useEntityPacket = phaseContext.getPacket();
    final net.minecraft.entity.Entity entity = useEntityPacket.getEntityFromWorld(player.world);
    if (entity == null) {
        // Something happened?
        return;
    }
    final World spongeWorld = EntityUtil.getSpongeWorld(player);
    EntityUtil.toMixin(entity).setNotifier(player.getUniqueID());
    phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> {
        final PrettyPrinter printer = new PrettyPrinter(80);
        printer.add("Processing Interact Entity").centre().hr();
        printer.add("The blocks captured are:");
        for (BlockSnapshot blockSnapshot : blocks) {
            printer.add("  Block: %s", blockSnapshot);
        }
        printer.trace(System.err);
    });
    phaseContext.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
        final PrettyPrinter printer = new PrettyPrinter(80);
        printer.add("Processing Interact Entity").centre().hr();
        printer.add("The entities captured are:");
        for (Entity capturedEntity : entities) {
            printer.add("  Entity: %s", capturedEntity);
        }
        printer.trace(System.err);
    });
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(player);
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.PLACEMENT);
        phaseContext.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(entities -> {
            final List<Entity> items = entities.stream().map(EntityUtil::fromNative).collect(Collectors.toList());
            SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), items);
            SpongeImpl.postEvent(event);
            if (!event.isCancelled()) {
                processSpawnedEntities(player, event);
            }
        });
    }
    phaseContext.getCapturedEntityDropSupplier().acceptIfNotEmpty(map -> {
        final PrettyPrinter printer = new PrettyPrinter(80);
        printer.add("Processing Interact Entity").centre().hr();
        printer.add("The item stacks captured are: ");
        for (Map.Entry<UUID, Collection<ItemDropData>> entry : map.asMap().entrySet()) {
            printer.add("  - Entity with UUID: %s", entry.getKey());
            for (ItemDropData stack : entry.getValue()) {
                printer.add("    - %s", stack);
            }
        }
        printer.trace(System.err);
    });
    phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(snapshots -> TrackingUtil.processBlockCaptures(snapshots, this, phaseContext));
}
Also used : CPacketUseEntity(net.minecraft.network.play.client.CPacketUseEntity) Entity(org.spongepowered.api.entity.Entity) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) CPacketUseEntity(net.minecraft.network.play.client.CPacketUseEntity) PrettyPrinter(org.spongepowered.asm.util.PrettyPrinter) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Collection(java.util.Collection) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) UUID(java.util.UUID) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) Map(java.util.Map)

Example 35 with SpawnEntityEvent

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

the class PacketState method spawnEntity.

/**
 * Defaulted method for packet phase states to spawn an entity directly.
 * This should be overridden by all packet phase states that are handling spawns
 * customarily with contexts and such. Captured entities are handled in
 * their respective {@link PacketState#unwind(PhaseContext)}s.
 *
 * @param context
 * @param entity
 * @param chunkX
 * @param chunkZ
 * @return True if the entity was spawned
 */
public boolean spawnEntity(P context, Entity entity, int chunkX, int chunkZ) {
    final net.minecraft.entity.Entity minecraftEntity = (net.minecraft.entity.Entity) entity;
    final WorldServer minecraftWorld = (WorldServer) minecraftEntity.world;
    final Player player = context.getSource(Player.class).orElseThrow(TrackingUtil.throwWithContext("Expected to be capturing a player", context));
    final ArrayList<Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(player);
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.PLACEMENT);
        Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, player);
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, player);
        final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
        SpongeImpl.postEvent(event);
        if (!event.isCancelled()) {
            for (Entity newEntity : event.getEntities()) {
                EntityUtil.toMixin(newEntity).setCreator(player.getUniqueId());
                ((IMixinWorldServer) minecraftWorld).forceSpawnEntity(newEntity);
            }
            return true;
        }
    }
    return false;
}
Also used : Entity(org.spongepowered.api.entity.Entity) Player(org.spongepowered.api.entity.living.player.Player) ArrayList(java.util.ArrayList) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager)

Aggregations

SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)44 Entity (org.spongepowered.api.entity.Entity)41 ArrayList (java.util.ArrayList)30 CauseStackManager (org.spongepowered.api.event.CauseStackManager)23 User (org.spongepowered.api.entity.living.player.User)18 EntityItem (net.minecraft.entity.item.EntityItem)17 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)15 List (java.util.List)11 DropItemEvent (org.spongepowered.api.event.item.inventory.DropItemEvent)11 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)11 Sponge (org.spongepowered.api.Sponge)10 SpongeEventFactory (org.spongepowered.api.event.SpongeEventFactory)10 SpongeImpl (org.spongepowered.common.SpongeImpl)10 EntityUtil (org.spongepowered.common.entity.EntityUtil)10 World (org.spongepowered.api.world.World)9 Collection (java.util.Collection)8 EntityPlayerMP (net.minecraft.entity.player.EntityPlayerMP)8 TileEntity (org.spongepowered.api.block.tileentity.TileEntity)8 ItemStack (org.spongepowered.api.item.inventory.ItemStack)8 ItemDropData (org.spongepowered.common.event.tracking.context.ItemDropData)8