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;
}
}
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;
}
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;
}
}
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
}
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;
}
Aggregations