Search in sources :

Example 16 with ItemDropData

use of org.spongepowered.common.event.tracking.context.ItemDropData in project SpongeCommon by SpongePowered.

the class MixinSpongeImplHooks_Item_Pre_Merge method addItemStackToListForSpawning.

/**
 * @author gabizou - April 7th, 2016
 * @reason Iterates over the collection to find possible matches for any merges that can take place.
 *
 * @param itemStacks The collection of item stacks to add on to
 * @param data The item stack being merged in
 */
@Overwrite
public static void addItemStackToListForSpawning(Collection<ItemDropData> itemStacks, ItemDropData data) {
    final net.minecraft.item.ItemStack itemStack = data.getStack();
    if (itemStack.isEmpty()) {
        return;
    }
    boolean addToList = true;
    final boolean isPlayerDrop = data instanceof ItemDropData.Player;
    if (itemStacks.isEmpty()) {
        itemStacks.add(data);
        return;
    }
    for (ItemDropData existingData : itemStacks) {
        final net.minecraft.item.ItemStack existing = existingData.getStack();
        if (existing.isEmpty()) {
            continue;
        }
        final boolean isExistingPlayer = existingData instanceof ItemDropData.Player;
        if (isExistingPlayer && !isPlayerDrop || !isExistingPlayer && isPlayerDrop) {
            continue;
        }
        if (isExistingPlayer) {
            final ItemDropData.Player existingPlayerData = (ItemDropData.Player) existingData;
            final ItemDropData.Player playerData = (ItemDropData.Player) data;
            if (existingPlayerData.isTrace() ^ playerData.isTrace()) {
                continue;
            }
            if (existingPlayerData.isDropAround() ^ playerData.isDropAround()) {
                continue;
            }
        }
        if (existing.getItem() != itemStack.getItem()) {
            continue;
        } else if (existing.hasTagCompound() ^ itemStack.hasTagCompound()) {
            continue;
        } else if (existing.hasTagCompound() && !existing.getTagCompound().equals(itemStack.getTagCompound())) {
            continue;
        } else if (existing.isEmpty()) {
            continue;
        } else if (existing.getItem().getHasSubtypes() && existing.getMetadata() != itemStack.getMetadata()) {
            continue;
        }
        // now to actually merge the itemstacks
        final int existingStackSize = existing.getCount();
        final int addingStackSize = itemStack.getCount();
        final int existingMaxStackSize = existing.getMaxStackSize();
        final int proposedStackSize = existingStackSize + addingStackSize;
        if (existingMaxStackSize < proposedStackSize) {
            existing.setCount(existingMaxStackSize);
            itemStack.setCount(proposedStackSize - existingMaxStackSize);
            addToList = true;
        // Basically, if we are overflowing the current existing stack, we can delegate to the
        // next "equals" item stack to potentially merge into that stack as well
        } else {
            existing.setCount(proposedStackSize);
            itemStack.setCount(0);
            addToList = false;
            break;
        }
    }
    if (addToList) {
        if (!itemStack.isEmpty() || itemStack.getCount() > 0) {
            itemStacks.add(data);
        }
    }
}
Also used : ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 17 with ItemDropData

use of org.spongepowered.common.event.tracking.context.ItemDropData 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

ItemDropData (org.spongepowered.common.event.tracking.context.ItemDropData)17 EntityItem (net.minecraft.entity.item.EntityItem)13 Entity (org.spongepowered.api.entity.Entity)12 CauseStackManager (org.spongepowered.api.event.CauseStackManager)12 DropItemEvent (org.spongepowered.api.event.item.inventory.DropItemEvent)12 World (org.spongepowered.api.world.World)11 ArrayList (java.util.ArrayList)10 UUID (java.util.UUID)10 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)8 Collection (java.util.Collection)7 Map (java.util.Map)7 BlockPos (net.minecraft.util.math.BlockPos)6 PrettyPrinter (org.spongepowered.asm.util.PrettyPrinter)6 List (java.util.List)5 Collectors (java.util.stream.Collectors)5 EntityPlayerMP (net.minecraft.entity.player.EntityPlayerMP)5 WorldServer (net.minecraft.world.WorldServer)5 Sponge (org.spongepowered.api.Sponge)5 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)5 SpongeEventFactory (org.spongepowered.api.event.SpongeEventFactory)5