Search in sources :

Example 1 with ConstructEntityEvent

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

the class EntityUtil method playerDropItem.

@Nullable
public static EntityItem playerDropItem(IMixinEntityPlayer mixinPlayer, ItemStack droppedItem, boolean dropAround, boolean traceItem) {
    mixinPlayer.shouldRestoreInventory(false);
    final EntityPlayer player = EntityUtil.toNative(mixinPlayer);
    final double posX = player.posX;
    final double adjustedPosY = player.posY - 0.3 + player.getEyeHeight();
    final double posZ = player.posZ;
    // Now the real fun begins.
    final ItemStack item;
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(player);
        // FIRST we want to throw the DropItemEvent.PRE
        final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(droppedItem);
        final List<ItemStackSnapshot> original = new ArrayList<>();
        original.add(snapshot);
        final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
        SpongeImpl.postEvent(dropEvent);
        if (dropEvent.isCancelled()) {
            mixinPlayer.shouldRestoreInventory(true);
            return null;
        }
        if (dropEvent.getDroppedItems().isEmpty()) {
            return null;
        }
        // SECOND throw the ConstructEntityEvent
        Transform<World> suggested = new Transform<>(mixinPlayer.getWorld(), new Vector3d(posX, adjustedPosY, posZ));
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
        ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.ITEM, suggested);
        SpongeImpl.postEvent(event);
        if (event.isCancelled()) {
            mixinPlayer.shouldRestoreInventory(true);
            return null;
        }
        item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.getDroppedItems().get(0));
        if (item == null) {
            mixinPlayer.shouldRestoreInventory(true);
            return null;
        }
        final PhaseData peek = PhaseTracker.getInstance().getCurrentPhaseData();
        final IPhaseState currentState = peek.state;
        final PhaseContext<?> phaseContext = peek.context;
        if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
            final Collection<ItemDropData> itemStacks;
            if (currentState.tracksEntitySpecificDrops()) {
                final Multimap<UUID, ItemDropData> multimap = phaseContext.getCapturedEntityDropSupplier().get();
                itemStacks = multimap.get(player.getUniqueID());
            } else {
                itemStacks = phaseContext.getCapturedItemStackSupplier().get();
            }
            SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.Player.player(player).stack(item).trace(traceItem).motion(createDropMotion(dropAround, player, mixinPlayer.getRandom())).dropAround(dropAround).position(new Vector3d(posX, adjustedPosY, posZ)).build());
            return null;
        }
        EntityItem entityitem = new EntityItem(player.world, posX, adjustedPosY, posZ, droppedItem);
        entityitem.setPickupDelay(40);
        if (traceItem) {
            entityitem.setThrower(player.getName());
        }
        final Random random = mixinPlayer.getRandom();
        if (dropAround) {
            float f = random.nextFloat() * 0.5F;
            float f1 = random.nextFloat() * ((float) Math.PI * 2F);
            entityitem.motionX = -MathHelper.sin(f1) * f;
            entityitem.motionZ = MathHelper.cos(f1) * f;
            entityitem.motionY = 0.20000000298023224D;
        } else {
            float f2 = 0.3F;
            entityitem.motionX = -MathHelper.sin(player.rotationYaw * 0.017453292F) * MathHelper.cos(player.rotationPitch * 0.017453292F) * f2;
            entityitem.motionZ = MathHelper.cos(player.rotationYaw * 0.017453292F) * MathHelper.cos(player.rotationPitch * 0.017453292F) * f2;
            entityitem.motionY = -MathHelper.sin(player.rotationPitch * 0.017453292F) * f2 + 0.1F;
            float f3 = random.nextFloat() * ((float) Math.PI * 2F);
            f2 = 0.02F * random.nextFloat();
            entityitem.motionX += Math.cos(f3) * f2;
            entityitem.motionY += (random.nextFloat() - random.nextFloat()) * 0.1F;
            entityitem.motionZ += Math.sin(f3) * f2;
        }
        // FIFTH - Capture the entity maybe?
        if (currentState.doesCaptureEntityDrops()) {
            if (currentState.tracksEntitySpecificDrops()) {
                // We are capturing per entity drop
                phaseContext.getCapturedEntityItemDropSupplier().get().put(player.getUniqueID(), entityitem);
            } else {
                // We are adding to a general list - usually for EntityPhase.State.DEATH
                phaseContext.getCapturedItemsSupplier().get().add(entityitem);
            }
            // Return the item, even if it wasn't spawned in the world.
            return entityitem;
        }
        ItemStack itemstack = dropItemAndGetStack(player, entityitem);
        if (traceItem) {
            if (!itemstack.isEmpty()) {
                player.addStat(StatList.getDroppedObjectStats(itemstack.getItem()), droppedItem.getCount());
            }
            player.addStat(StatList.DROP);
        }
        return entityitem;
    }
}
Also used : ArrayList(java.util.ArrayList) World(org.spongepowered.api.world.World) Random(java.util.Random) CauseStackManager(org.spongepowered.api.event.CauseStackManager) UUID(java.util.UUID) EntityItem(net.minecraft.entity.item.EntityItem) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) Vector3d(com.flowpowered.math.vector.Vector3d) IMixinEntityPlayer(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer) EntityPlayer(net.minecraft.entity.player.EntityPlayer) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.item.ItemStack) Transform(org.spongepowered.api.entity.Transform) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) Nullable(javax.annotation.Nullable)

Example 2 with ConstructEntityEvent

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

the class SpongeCommonEventFactory method throwDropItemAndConstructEvent.

/**
 * @author gabizou - April 19th, 2018
 * Creates two events here:
 * - {@link DropItemEvent}
 * - {@link ConstructEntityEvent}
 *
 * This is to reduce the code size from normal entity drops and player drops.
 * While player drops usually require performing position and motion modifications,
 * we return the item stack if it is to be thrown (this allows the event to have a
 * say in what item is dropped).
 *
 * @param entity The entity throwing the item
 * @param posX The position x for the item stack to spawn
 * @param posY The position y for the item stack to spawn
 * @param posZ The position z for the item stack to spawn
 * @param snapshot The item snapshot of the item to drop
 * @param original The original list to be used
 * @param frame
 * @return The item if it is to be spawned, null if to be ignored
 */
@Nullable
public static ItemStack throwDropItemAndConstructEvent(final net.minecraft.world.entity.Entity entity, final double posX, final double posY, final double posZ, final ItemStackSnapshot snapshot, final List<ItemStackSnapshot> original, final CauseStackManager.StackFrame frame) {
    final ItemStack item;
    frame.pushCause(entity);
    // FIRST we want to throw the DropItemEvent.PRE
    final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(frame.currentCause(), ImmutableList.of(snapshot), original);
    SpongeCommon.post(dropEvent);
    if (dropEvent.isCancelled()) {
        return null;
    }
    if (dropEvent.droppedItems().isEmpty()) {
        return null;
    }
    // SECOND throw the ConstructEntityEvent
    frame.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
    final ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(frame.currentCause(), ServerLocation.of((ServerWorld) entity.level, posX, posY, posZ), new Vector3d(0, 0, 0), EntityTypes.ITEM.get());
    frame.removeContext(EventContextKeys.SPAWN_TYPE);
    SpongeCommon.post(event);
    if (event.isCancelled()) {
        return null;
    }
    item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.droppedItems().get(0));
    if (item == null) {
        return null;
    }
    return item;
}
Also used : ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) ServerWorld(org.spongepowered.api.world.server.ServerWorld) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Vector3d(org.spongepowered.math.vector.Vector3d) ItemStack(net.minecraft.world.item.ItemStack) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 3 with ConstructEntityEvent

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

the class EntityUtil method entityOnDropItem.

/**
 * A simple redirected static util method for {@link Entity#entityDropItem(ItemStack, float)}
 * for easy debugging.
 * @param entity
 * @param itemStack
 * @param offsetY
 * @return
 */
public static EntityItem entityOnDropItem(Entity entity, ItemStack itemStack, float offsetY) {
    final IMixinEntity mixinEntity = EntityUtil.toMixin(entity);
    final IMixinEntityPlayer mixinPlayer = entity instanceof Player ? (IMixinEntityPlayer) entity : null;
    // Now the real fun begins.
    final ItemStack item;
    final double posX = entity.posX;
    final double posY = entity.posY + offsetY;
    final double posZ = entity.posZ;
    if (itemStack.isEmpty()) {
        return null;
    }
    // FIRST we want to throw the DropItemEvent.PRE
    final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(itemStack);
    final List<ItemStackSnapshot> original = new ArrayList<>();
    original.add(snapshot);
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(entity);
        final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
        SpongeImpl.postEvent(dropEvent);
        if (dropEvent.isCancelled()) {
            if (mixinPlayer != null) {
                mixinPlayer.shouldRestoreInventory(true);
            }
            return null;
        }
        if (dropEvent.getDroppedItems().isEmpty()) {
            return null;
        }
        // SECOND throw the ConstructEntityEvent
        Transform<World> suggested = new Transform<>(mixinEntity.getWorld(), new Vector3d(posX, entity.posY + offsetY, posZ));
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
        ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.ITEM, suggested);
        SpongeImpl.postEvent(event);
        item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.getDroppedItems().get(0));
        if (item == null) {
            if (mixinPlayer != null) {
                mixinPlayer.shouldRestoreInventory(true);
            }
            return null;
        }
        final PhaseData peek = PhaseTracker.getInstance().getCurrentPhaseData();
        final IPhaseState currentState = peek.state;
        final PhaseContext<?> phaseContext = peek.context;
        if (item.isEmpty()) {
            return null;
        }
        if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
            if (currentState.tracksEntitySpecificDrops()) {
                final Multimap<UUID, ItemDropData> multimap = phaseContext.getCapturedEntityDropSupplier().get();
                final Collection<ItemDropData> itemStacks = multimap.get(entity.getUniqueID());
                SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
                return null;
            }
            final List<ItemDropData> itemStacks = phaseContext.getCapturedItemStackSupplier().get();
            SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
            return null;
        }
        EntityItem entityitem = new EntityItem(entity.world, posX, posY, posZ, item);
        entityitem.setDefaultPickupDelay();
        // FIFTH - Capture the entity maybe?
        if (currentState.doesCaptureEntityDrops()) {
            if (currentState.tracksEntitySpecificDrops()) {
                // We are capturing per entity drop
                phaseContext.getCapturedEntityItemDropSupplier().get().put(entity.getUniqueID(), entityitem);
            } else {
                // We are adding to a general list - usually for EntityPhase.State.DEATH
                phaseContext.getCapturedItemsSupplier().get().add(entityitem);
            }
            // Return the item, even if it wasn't spawned in the world.
            return entityitem;
        }
        // FINALLY - Spawn the entity in the world if all else didn't fail
        entity.world.spawnEntity(entityitem);
        return entityitem;
    }
}
Also used : ArrayList(java.util.ArrayList) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World) CauseStackManager(org.spongepowered.api.event.CauseStackManager) IMixinEntityPlayer(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer) UUID(java.util.UUID) EntityItem(net.minecraft.entity.item.EntityItem) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Player(org.spongepowered.api.entity.living.player.Player) IMixinEntityPlayer(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer) EntityPlayer(net.minecraft.entity.player.EntityPlayer) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) Vector3d(com.flowpowered.math.vector.Vector3d) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.item.ItemStack) Transform(org.spongepowered.api.entity.Transform) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData)

Example 4 with ConstructEntityEvent

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

the class MixinWorldServer method updateBlocks.

/**
 * @author blood - July 1st, 2016
 * @author gabizou - July 1st, 2016 - Update to 1.10 and cause tracking
 *
 * @reason Added chunk and block tick optimizations, timings, cause tracking, and pre-construction events.
 */
@SuppressWarnings("unchecked")
@Override
@Overwrite
protected void updateBlocks() {
    this.playerCheckLight();
    if (this.worldInfo.getTerrainType() == WorldType.DEBUG_ALL_BLOCK_STATES) {
        Iterator<net.minecraft.world.chunk.Chunk> iterator1 = this.playerChunkMap.getChunkIterator();
        while (iterator1.hasNext()) {
            iterator1.next().onTick(false);
        }
        // Sponge: Add return
        return;
    }
    // else // Sponge - Remove unnecessary else
    // { //
    int i = this.shadow$getGameRules().getInt("randomTickSpeed");
    boolean flag = this.isRaining();
    boolean flag1 = this.isThundering();
    // this.profiler.startSection("pollingChunks"); // Sponge - Don't use the profiler
    // Sponge - get the cause tracker
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    // Sponge: Use SpongeImplHooks for Forge
    for (Iterator<net.minecraft.world.chunk.Chunk> iterator = // this.profiler.endSection()) // Sponge - don't use the profiler
    SpongeImplHooks.getChunkIterator((WorldServer) (Object) this); // this.profiler.endSection()) // Sponge - don't use the profiler
    iterator.hasNext(); ) {
        // this.profiler.startSection("getChunk"); // Sponge - Don't use the profiler
        net.minecraft.world.chunk.Chunk chunk = iterator.next();
        final net.minecraft.world.World world = chunk.getWorld();
        int j = chunk.x * 16;
        int k = chunk.z * 16;
        // this.profiler.endStartSection("checkNextLight"); // Sponge - Don't use the profiler
        // Sponge - Timings
        this.timings.updateBlocksCheckNextLight.startTiming();
        chunk.enqueueRelightChecks();
        // Sponge - Timings
        this.timings.updateBlocksCheckNextLight.stopTiming();
        // this.profiler.endStartSection("tickChunk"); // Sponge - Don't use the profiler
        // Sponge - Timings
        this.timings.updateBlocksChunkTick.startTiming();
        chunk.onTick(false);
        // Sponge - Timings
        this.timings.updateBlocksChunkTick.stopTiming();
        // Sponge start - if surrounding neighbors are not loaded, skip
        if (!((IMixinChunk) chunk).areNeighborsLoaded()) {
            continue;
        }
        // Sponge end
        // this.profiler.endStartSection("thunder"); // Sponge - Don't use the profiler
        // Sponge start
        this.timings.updateBlocksThunder.startTiming();
        // if (this.provider.canDoLightning(chunk) && flag && flag1 && this.rand.nextInt(100000) == 0) // Sponge - Add SpongeImplHooks for forge
        if (this.weatherThunderEnabled && SpongeImplHooks.canDoLightning(this.provider, chunk) && flag && flag1 && this.rand.nextInt(100000) == 0) {
            try (final PhaseContext<?> context = TickPhase.Tick.WEATHER.createPhaseContext().source(this).buildAndSwitch()) {
                // Sponge end
                this.updateLCG = this.updateLCG * 3 + 1013904223;
                int l = this.updateLCG >> 2;
                BlockPos blockpos = this.adjustPosToNearbyEntity(new BlockPos(j + (l & 15), 0, k + (l >> 8 & 15)));
                if (this.isRainingAt(blockpos)) {
                    DifficultyInstance difficultyinstance = this.getDifficultyForLocation(blockpos);
                    // Sponge - create a transform to be used for events
                    final Transform<org.spongepowered.api.world.World> transform = new Transform<>(this, VecHelper.toVector3d(blockpos).toDouble());
                    if (world.getGameRules().getBoolean("doMobSpawning") && this.rand.nextDouble() < (double) difficultyinstance.getAdditionalDifficulty() * 0.01D) {
                        // Sponge Start - Throw construction events
                        try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
                            Sponge.getCauseStackManager().pushCause(this.getWeather());
                            Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.WEATHER);
                            ConstructEntityEvent.Pre constructEntityEvent = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.HORSE, transform);
                            SpongeImpl.postEvent(constructEntityEvent);
                            if (!constructEntityEvent.isCancelled()) {
                                // Sponge End
                                EntitySkeletonHorse entityhorse = new EntitySkeletonHorse((WorldServer) (Object) this);
                                entityhorse.setTrap(true);
                                entityhorse.setGrowingAge(0);
                                entityhorse.setPosition(blockpos.getX(), blockpos.getY(), blockpos.getZ());
                                this.spawnEntity(entityhorse);
                            // Sponge Start - Throw a construct event for the lightning
                            }
                            ConstructEntityEvent.Pre lightning = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.LIGHTNING, transform);
                            SpongeImpl.postEvent(lightning);
                            if (!lightning.isCancelled()) {
                                LightningEvent.Pre lightningPre = SpongeEventFactory.createLightningEventPre(frame.getCurrentCause());
                                if (!SpongeImpl.postEvent(lightningPre)) {
                                    // Sponge End
                                    this.addWeatherEffect(new EntityLightningBolt(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), true));
                                }
                            }
                        // Sponge - Brackets.
                        }
                    } else {
                        // Sponge start - Throw construction event for lightningbolts
                        try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
                            Sponge.getCauseStackManager().pushCause(this.getWeather());
                            Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.WEATHER);
                            ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.LIGHTNING, transform);
                            SpongeImpl.postEvent(event);
                            if (!event.isCancelled()) {
                                LightningEvent.Pre lightningPre = SpongeEventFactory.createLightningEventPre(frame.getCurrentCause());
                                if (!SpongeImpl.postEvent(lightningPre)) {
                                    // Sponge End
                                    this.addWeatherEffect(new EntityLightningBolt(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), true));
                                }
                            }
                        // Sponge - Brackets.
                        }
                    }
                }
            }
        // Sponge - brackets
        // Sponge End
        }
        // Sponge - Stop thunder timing
        this.timings.updateBlocksThunder.stopTiming();
        // Sponge - Start thunder timing
        this.timings.updateBlocksIceAndSnow.startTiming();
        // if (this.rand.nextInt(16) == 0) // Sponge - Rewrite to use our boolean, and forge hook
        if (this.weatherIceAndSnowEnabled && SpongeImplHooks.canDoRainSnowIce(this.provider, chunk) && this.rand.nextInt(16) == 0) {
            // Sponge Start - Enter weather phase for snow and ice and flooding.
            try (final PhaseContext<?> context = TickPhase.Tick.WEATHER.createPhaseContext().source(this).buildAndSwitch()) {
                // Sponge End
                this.updateLCG = this.updateLCG * 3 + 1013904223;
                int j2 = this.updateLCG >> 2;
                BlockPos blockpos1 = this.getPrecipitationHeight(new BlockPos(j + (j2 & 15), 0, k + (j2 >> 8 & 15)));
                BlockPos blockpos2 = blockpos1.down();
                if (this.canBlockFreezeNoWater(blockpos2)) {
                    this.setBlockState(blockpos2, Blocks.ICE.getDefaultState());
                }
                if (flag && this.canSnowAt(blockpos1, true)) {
                    this.setBlockState(blockpos1, Blocks.SNOW_LAYER.getDefaultState());
                }
                if (flag && this.getBiome(blockpos2).canRain()) {
                    this.getBlockState(blockpos2).getBlock().fillWithRain((WorldServer) (Object) this, blockpos2);
                }
            }
        // Sponge - brackets
        }
        // Sponge - Stop ice and snow timing
        this.timings.updateBlocksIceAndSnow.stopTiming();
        // Sponge - Start random block tick timing
        this.timings.updateBlocksRandomTick.startTiming();
        if (i > 0) {
            for (ExtendedBlockStorage extendedblockstorage : chunk.getBlockStorageArray()) {
                if (extendedblockstorage != net.minecraft.world.chunk.Chunk.NULL_BLOCK_STORAGE && extendedblockstorage.needsRandomTick()) {
                    for (int i1 = 0; i1 < i; ++i1) {
                        this.updateLCG = this.updateLCG * 3 + 1013904223;
                        int j1 = this.updateLCG >> 2;
                        int k1 = j1 & 15;
                        int l1 = j1 >> 8 & 15;
                        int i2 = j1 >> 16 & 15;
                        IBlockState iblockstate = extendedblockstorage.get(k1, i2, l1);
                        Block block = iblockstate.getBlock();
                        if (block.getTickRandomly()) {
                            // Sponge start - capture random tick
                            // Remove the random tick for cause tracking
                            // block.randomTick(this, new BlockPos(k1 + j, i2 + extendedblockstorage.getYLocation(), l1 + k), iblockstate, this.rand);
                            BlockPos pos = new BlockPos(k1 + j, i2 + extendedblockstorage.getYLocation(), l1 + k);
                            IMixinBlock spongeBlock = (IMixinBlock) block;
                            spongeBlock.getTimingsHandler().startTiming();
                            final PhaseData currentTuple = phaseTracker.getCurrentPhaseData();
                            final IPhaseState phaseState = currentTuple.state;
                            if (phaseState.alreadyCapturingBlockTicks(currentTuple.context)) {
                                block.randomTick(world, pos, iblockstate, this.rand);
                            } else {
                                TrackingUtil.randomTickBlock(phaseTracker, this, block, pos, iblockstate, this.rand);
                            }
                            spongeBlock.getTimingsHandler().stopTiming();
                        // Sponge end
                        }
                    // this.profiler.endSection(); // Sponge - Don't use the profiler
                    }
                }
            }
        }
    }
    // Sponge - Stop random block timing
    this.timings.updateBlocksRandomTick.stopTiming();
// this.profiler.endSection(); // Sponge - Don't use the profiler
// } // Sponge- Remove unecessary else
}
Also used : DifficultyInstance(net.minecraft.world.DifficultyInstance) EntityLightningBolt(net.minecraft.entity.effect.EntityLightningBolt) World(net.minecraft.world.World) IMixinBlock(org.spongepowered.common.interfaces.block.IMixinBlock) CauseStackManager(org.spongepowered.api.event.CauseStackManager) EntitySkeletonHorse(net.minecraft.entity.passive.EntitySkeletonHorse) BlockPos(net.minecraft.util.math.BlockPos) IMixinBlockPos(org.spongepowered.common.interfaces.util.math.IMixinBlockPos) Chunk(net.minecraft.world.chunk.Chunk) IBlockState(net.minecraft.block.state.IBlockState) PhaseData(org.spongepowered.common.event.tracking.PhaseData) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) World(net.minecraft.world.World) LightningEvent(org.spongepowered.api.event.action.LightningEvent) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) Chunk(net.minecraft.world.chunk.Chunk) ExtendedBlockStorage(net.minecraft.world.chunk.storage.ExtendedBlockStorage) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) Block(net.minecraft.block.Block) EnumSkyBlock(net.minecraft.world.EnumSkyBlock) IMixinBlock(org.spongepowered.common.interfaces.block.IMixinBlock) LocatableBlock(org.spongepowered.api.world.LocatableBlock) Transform(org.spongepowered.api.entity.Transform) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 5 with ConstructEntityEvent

use of org.spongepowered.api.event.entity.ConstructEntityEvent in project SpongeForge by SpongePowered.

the class MixinItemShears method itemInteractionForEntity.

/**
 * @author gabizou - June 21st, 2016
 * @reason Rewrites the forge handling of this to properly handle
 * when sheared drops are captured by whatever current phase the
 * {@link PhaseTracker} is in.
 *
 * Returns true if the item can be used on the given entity, e.g. shears on sheep.
 */
@Overwrite
@Override
public boolean itemInteractionForEntity(ItemStack itemstack, EntityPlayer player, EntityLivingBase entity, EnumHand hand) {
    if (entity.world.isRemote) {
        return false;
    }
    if (entity instanceof IShearable) {
        IShearable target = (IShearable) entity;
        BlockPos pos = new BlockPos(entity.posX, entity.posY, entity.posZ);
        if (target.isShearable(itemstack, entity.world, pos)) {
            List<ItemStack> drops = target.onSheared(itemstack, entity.world, pos, EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, itemstack));
            // Sponge Start - Handle drops according to the current phase
            final PhaseTracker phaseTracker = PhaseTracker.getInstance();
            final PhaseData currentData = phaseTracker.getCurrentPhaseData();
            final IPhaseState<?> currentState = currentData.state;
            final PhaseContext<?> phaseContext = currentData.context;
            final Random random = EntityUtil.fromNative(entity).getRandom();
            final IMixinEntity mixinEntity = EntityUtil.toMixin(entity);
            final double posX = entity.posX;
            final double posY = entity.posY + 1.0F;
            final double posZ = entity.posZ;
            final Vector3d position = new Vector3d(posX, posY, posZ);
            // Now the real fun begins.
            for (ItemStack drop : drops) {
                final ItemStack item;
                if (!drop.isEmpty()) {
                    try (final CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
                        // FIRST we want to throw the DropItemEvent.PRE
                        final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(drop);
                        final List<ItemStackSnapshot> original = new ArrayList<>();
                        original.add(snapshot);
                        Sponge.getCauseStackManager().pushCause(entity);
                        final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
                        if (dropEvent.isCancelled()) {
                            continue;
                        }
                        // SECOND throw the ConstructEntityEvent
                        Transform<World> suggested = new Transform<>(mixinEntity.getWorld(), position);
                        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
                        ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.ITEM, suggested);
                        SpongeImpl.postEvent(event);
                        item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.getDroppedItems().get(0));
                    }
                } else {
                    continue;
                }
                if (item == null) {
                    continue;
                }
                if (!item.isEmpty()) {
                    if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
                        if (currentState.tracksEntitySpecificDrops()) {
                            final Multimap<UUID, ItemDropData> multimap = phaseContext.getCapturedEntityDropSupplier().get();
                            final Collection<ItemDropData> itemStacks = multimap.get(entity.getUniqueID());
                            SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).motion(new Vector3d((random.nextFloat() - random.nextFloat()) * 0.1F, random.nextFloat() * 0.05F, (random.nextFloat() - random.nextFloat()) * 0.1F)).position(new Vector3d(posX, posY, posZ)).build());
                            continue;
                        }
                        final List<ItemDropData> itemStacks = phaseContext.getCapturedItemStackSupplier().get();
                        SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).motion(new Vector3d((random.nextFloat() - random.nextFloat()) * 0.1F, random.nextFloat() * 0.05F, (random.nextFloat() - random.nextFloat()) * 0.1F)).build());
                        continue;
                    }
                    EntityItem entityitem = new EntityItem(entity.world, posX, posY, posZ, item);
                    entityitem.setDefaultPickupDelay();
                    entityitem.motionY += random.nextFloat() * 0.05F;
                    entityitem.motionX += (random.nextFloat() - random.nextFloat()) * 0.1F;
                    entityitem.motionZ += (random.nextFloat() - random.nextFloat()) * 0.1F;
                    // FIFTH - Capture the entity maybe?
                    if (currentState.doesCaptureEntityDrops()) {
                        if (currentState.tracksEntitySpecificDrops()) {
                            // We are capturing per entity drop
                            phaseContext.getCapturedEntityItemDropSupplier().get().put(entity.getUniqueID(), entityitem);
                        } else {
                            // We are adding to a general list - usually for EntityPhase.State.DEATH
                            phaseContext.getCapturedItemsSupplier().get().add(entityitem);
                        }
                        // Return the item, even if it wasn't spawned in the world.
                        continue;
                    }
                    // FINALLY - Spawn the entity in the world if all else didn't fail
                    entity.world.spawnEntity(entityitem);
                }
            }
            // Sponge End
            itemstack.damageItem(1, entity);
        }
        return true;
    }
    return false;
}
Also used : ArrayList(java.util.ArrayList) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World) Random(java.util.Random) CauseStackManager(org.spongepowered.api.event.CauseStackManager) IShearable(net.minecraftforge.common.IShearable) BlockPos(net.minecraft.util.math.BlockPos) UUID(java.util.UUID) EntityItem(net.minecraft.entity.item.EntityItem) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) PhaseData(org.spongepowered.common.event.tracking.PhaseData) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Vector3d(com.flowpowered.math.vector.Vector3d) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.item.ItemStack) Transform(org.spongepowered.api.entity.Transform) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Aggregations

ConstructEntityEvent (org.spongepowered.api.event.entity.ConstructEntityEvent)5 Transform (org.spongepowered.api.entity.Transform)4 CauseStackManager (org.spongepowered.api.event.CauseStackManager)4 DropItemEvent (org.spongepowered.api.event.item.inventory.DropItemEvent)4 Vector3d (com.flowpowered.math.vector.Vector3d)3 ArrayList (java.util.ArrayList)3 UUID (java.util.UUID)3 EntityItem (net.minecraft.entity.item.EntityItem)3 ItemStack (net.minecraft.item.ItemStack)3 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)3 World (org.spongepowered.api.world.World)3 ItemDropData (org.spongepowered.common.event.tracking.context.ItemDropData)3 Random (java.util.Random)2 EntityPlayer (net.minecraft.entity.player.EntityPlayer)2 BlockPos (net.minecraft.util.math.BlockPos)2 Overwrite (org.spongepowered.asm.mixin.Overwrite)2 PhaseData (org.spongepowered.common.event.tracking.PhaseData)2 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)2 IMixinEntity (org.spongepowered.common.interfaces.entity.IMixinEntity)2 IMixinEntityPlayer (org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer)2