diff --git a/patchwork-events-entity/build.gradle b/patchwork-events-entity/build.gradle index 057f81d7..3133e6b4 100644 --- a/patchwork-events-entity/build.gradle +++ b/patchwork-events-entity/build.gradle @@ -3,5 +3,6 @@ version = getSubprojectVersion(project, "0.4.0") dependencies { compile project(path: ':patchwork-fml', configuration: 'dev') + compile project(path: ':patchwork-extensions-entity', configuration: 'dev') compile project(path: ':patchwork-extensions-item', configuration: 'dev') } diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemEvent.java new file mode 100644 index 00000000..621958a7 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemEvent.java @@ -0,0 +1,51 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.item; + +import net.minecraftforge.event.entity.EntityEvent; + +import net.minecraft.entity.ItemEntity; + +/** + * Base class for all ItemEntity events. Contains a reference to the + * ItemEntity of interest. For most ItemEntity events, there's little to no + * additional useful data from the firing method that isn't already contained + * within the ItemEntity instance. + */ +public class ItemEvent extends EntityEvent { + private final ItemEntity entityItem; + + /** + * Creates a new event for an EntityItem. + * + * @param itemEntity The EntityItem for this event + */ + public ItemEvent(ItemEntity itemEntity) { + super(itemEntity); + this.entityItem = itemEntity; + } + + /** + * The relevant EntityItem for this event, already cast for you. + */ + public ItemEntity getEntityItem() { + return entityItem; + } +} diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemExpireEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemExpireEvent.java new file mode 100644 index 00000000..c1e5b2ee --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemExpireEvent.java @@ -0,0 +1,52 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.item; + +import net.minecraft.entity.ItemEntity; + +/** + * Event that is fired when an ItemEntity's age has reached its maximum + * lifespan. Canceling this event will prevent the ItemEntity from being + * flagged as dead, thus staying it's removal from the world. If canceled + * it will add more time to the entities life equal to extraLife. + */ + +public class ItemExpireEvent extends ItemEvent { + private int extraLife; + + /** + * Creates a new event for an expiring EntityItem. + * + * @param entityItem The ItemEntity being deleted. + * @param extraLife The amount of time to be added to this entities lifespan if the event is canceled. + */ + public ItemExpireEvent(ItemEntity entityItem, int extraLife) { + super(entityItem); + this.setExtraLife(extraLife); + } + + public int getExtraLife() { + return extraLife; + } + + public void setExtraLife(int extraLife) { + this.extraLife = extraLife; + } +} diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemTossEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemTossEvent.java new file mode 100644 index 00000000..5851b7dc --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/item/ItemTossEvent.java @@ -0,0 +1,52 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.item; + +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; + +/** + * Event that is fired whenever a player tosses (Q) an item or drag-n-drops a + * stack of items outside the inventory GUI screens. Canceling the event will + * stop the items from entering the world, but will not prevent them being + * removed from the inventory - and thus removed from the system. + */ +// TODO: Call Location - ForgeHook#onPlayerTossEvent -> PlayerEntity#dropSelectedItem + PlayerEntity#dropItem +public class ItemTossEvent extends ItemEvent { + private final PlayerEntity player; + + /** + * Creates a new event for ItemEntities tossed by a player. + * + * @param entityItem The ItemEntity being tossed. + * @param player The player tossing the item. + */ + public ItemTossEvent(ItemEntity entityItem, PlayerEntity player) { + super(entityItem); + this.player = player; + } + + /** + * The player tossing the item. + */ + public PlayerEntity getPlayer() { + return player; + } +} diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java new file mode 100644 index 00000000..b51ee15a --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/EntityItemPickupEvent.java @@ -0,0 +1,46 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.entity.player; + +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; + +/** + * This event is called when a player collides with a EntityItem on the ground. + * The event can be canceled, and no further processing will be done. + * + *

You can set the result of this event to ALLOW which will trigger the + * processing of achievements, FML's event, play the sound, and kill the + * entity if all the items are picked up. + * + *

setResult(ALLOW) is the same as the old setHandled() + */ +public class EntityItemPickupEvent extends PlayerEvent { + private final ItemEntity item; + + public EntityItemPickupEvent(PlayerEntity player, ItemEntity item) { + super(player); + this.item = item; + } + + public ItemEntity getItem() { + return item; + } +} diff --git a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java index 4a0e47c9..5ab9ce78 100644 --- a/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java +++ b/patchwork-events-entity/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java @@ -21,6 +21,8 @@ import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraft.entity.ItemEntity; +import net.minecraft.item.ItemStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.Entity; @@ -131,6 +133,31 @@ public boolean isWasDeath() { } } + public static class ItemPickupEvent extends PlayerEvent { + /** + * Original EntityItem with current remaining stack size. + */ + private final ItemEntity originalEntity; + /** + * Clone item stack, containing the item and amount picked up. + */ + private final ItemStack stack; + + public ItemPickupEvent(PlayerEntity player, ItemEntity entPickedUp, ItemStack stack) { + super(player); + this.originalEntity = entPickedUp; + this.stack = stack; + } + + public ItemStack getStack() { + return stack; + } + + public ItemEntity getOriginalEntity() { + return originalEntity; + } + } + /*TODO Events: HarvestCheck BreakSpeed @@ -138,7 +165,6 @@ public boolean isWasDeath() { LoadFromFile SaveToFile Visibility - ItemPickupEvent ItemCraftedEvent ItemSmeltedEvent PlayerLoggedOutEvent diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java index 3c753fd4..40415c77 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java @@ -19,10 +19,14 @@ package net.patchworkmc.impl.event.entity; +import com.google.common.collect.Lists; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeEntity; import net.minecraftforge.common.extensions.IForgeItem; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.item.ItemExpireEvent; +import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; @@ -32,6 +36,7 @@ import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.event.entity.living.LivingSpawnEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -43,6 +48,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnType; import net.minecraft.entity.damage.DamageSource; @@ -181,6 +187,51 @@ public static boolean attackEntity(PlayerEntity player, Entity target) { return !item.onLeftClickEntity(stack, player, target); } + public static void firePlayerItemPickupEvent(PlayerEntity player, ItemEntity item, ItemStack clone) { + MinecraftForge.EVENT_BUS.post(new PlayerEvent.ItemPickupEvent(player, item, clone)); + } + + public static boolean onItemPickup(ItemEntity entityItem, PlayerEntity player) { + return MinecraftForge.EVENT_BUS.post(new EntityItemPickupEvent(player, entityItem)); + } + + public static int onItemExpire(ItemEntity entity, ItemStack item) { + if (item.isEmpty()) { + return -1; + } + + ItemExpireEvent event = new ItemExpireEvent(entity, 6000); + // TODO: ItemExpireEvent event = new ItemExpireEvent(entity, (item.isEmpty() ? 6000 : item.getItem().getEntityLifespan(item, entity.world))); + + if (!MinecraftForge.EVENT_BUS.post(event)) { + return -1; + } + + return event.getExtraLife(); + } + + public static ItemEntity onPlayerTossEvent(PlayerEntity player, ItemStack item, boolean includeName) { + ((IForgeEntity) player).captureDrops(Lists.newArrayList()); + ItemEntity ret = player.dropItem(item, false, includeName); + ((IForgeEntity) player).captureDrops(null); + + if (ret == null) { + return null; + } + + ItemTossEvent event = new ItemTossEvent(ret, player); + + if (MinecraftForge.EVENT_BUS.post(event)) { + return null; + } + + if (!player.world.isClient) { + player.getEntityWorld().spawnEntity(event.getEntityItem()); + } + + return event.getEntityItem(); + } + @Override public void onInitialize() { UseItemCallback.EVENT.register((player, world, hand) -> { diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java index 94513412..ed50dfdc 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinEntity.java @@ -19,22 +19,28 @@ package net.patchworkmc.mixin.event.entity; +import java.util.Collection; + +import net.minecraftforge.common.extensions.IForgeEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityType; +import net.minecraft.entity.ItemEntity; import net.minecraft.world.World; import net.patchworkmc.impl.event.entity.EntityEvents; @Mixin(Entity.class) -public abstract class MixinEntity { +public abstract class MixinEntity implements IForgeEntity { @Shadow private float standingEyeHeight; @@ -44,6 +50,9 @@ public abstract class MixinEntity { @Shadow protected abstract float getEyeHeight(EntityPose pose, EntityDimensions dimensions); + @Unique + private Collection captureDrops = null; + @Inject(method = "", at = @At("RETURN")) public void hookConstructor(EntityType type, World world, CallbackInfo ci) { Entity entity = (Entity) (Object) this; @@ -52,4 +61,23 @@ public void hookConstructor(EntityType type, World world, CallbackInfo ci) { EntityEvents.onEntityConstruct(entity); } + + @Redirect(method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ItemEntity;setToDefaultPickupDelay()V")) + private void addToCaptureDrops(ItemEntity entity) { + if (this.captureDrops != null) { + this.captureDrops.add(entity); + } + } + + @Override + public Collection captureDrops() { + return captureDrops; + } + + @Override + public Collection captureDrops(Collection replacement) { + Collection cache = this.captureDrops; + this.captureDrops = replacement; + return cache; + } } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java new file mode 100644 index 00000000..05e8b400 --- /dev/null +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java @@ -0,0 +1,132 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.patchworkmc.mixin.event.entity; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.World; + +import net.patchworkmc.impl.event.entity.EntityEvents; + +@Mixin(ItemEntity.class) +public abstract class MixinItemEntity { + @Shadow + private int pickupDelay; + + @Shadow + public abstract ItemStack getStack(); + + @Unique + public int lifespan = 6000; + + // TODO -> Forge has exposed 'lifespan' (hardcoded to 6000) through IForgeItemStack/IForgeItem#getEntityLifespan + /* + @Inject(method = "(Lnet/minecraft/world/World;DDDLnet/minecraft/item/ItemStack;)V", at = @At("RETURN")) + private void modifyLifespan(World world, double x, double y, double z, ItemStack stack, CallbackInfo ci) { + this.lifespan = stack.getItem() == null ? 6000 : ((IForgeItemStack) stack).getEntityLifespan(world); + } + */ + + // TODO -> Forge has a callback at IForgeItemStack/IForgeItem#onEntityItemUpdate + /* + @Inject(method = "tick", at = @At("HEAD"), cancellable = true) + private void onUpdate(CallbackInfo ci) { + if ((IForgeItemStack) stack).onEntityItemUpdate((ItemEntity) (Object) this) { + ci.cancel(); + } + } + */ + + @ModifyConstant(method = "tick", constant = @Constant(intValue = 6000)) + private int onTickCheckLifespan(int original) { + return lifespan; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ItemEntity;remove()V")) + private void fireOnItemExpire(ItemEntity item) { + int hook = EntityEvents.onItemExpire(item, getStack()); + + if (hook < 0) { + item.remove(); + } else { + this.lifespan += hook; + } + } + + @Inject(method = "writeCustomDataToTag", at = @At("HEAD")) + private void addLifespanToTag(CompoundTag tag, CallbackInfo ci) { + tag.putInt("Lifespan", lifespan); + } + + @Inject(method = "readCustomDataFromTag", at = @At("HEAD")) + private void readLifespanInTag(CompoundTag tag, CallbackInfo ci) { + if (tag.contains("Lifespan")) { + this.lifespan = tag.getInt("Lifespan"); + } + } + + @Redirect(method = "onPlayerCollision", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/world/World;isClient:Z")) + private boolean checkPickupDelay(World world) { + return world.isClient && this.pickupDelay <= 0; + } + + @Inject(method = "onPlayerCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ItemEntity;getStack()Lnet/minecraft/item/ItemStack;"), cancellable = true) + private void fireEntityItemPickup(PlayerEntity player, CallbackInfo ci) { + if (EntityEvents.onItemPickup((ItemEntity) (Object) this, player)) { + ci.cancel(); + } + } + + @ModifyConstant(method = "onPlayerCollision", constant = @Constant(intValue = 6000, ordinal = 0)) + private int onPlayerCollideCheckLifespan(int original) { + return lifespan; + } + + @Redirect(method = "onPlayerCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;sendPickup(Lnet/minecraft/entity/Entity;I)V")) + private void onPlayerItemPickup(PlayerEntity entity, Entity item, int count) { + EntityEvents.firePlayerItemPickupEvent(entity, (ItemEntity) item, getStack().copy()); + } + + @Inject(method = "onPlayerCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/ItemEntity;remove()V")) + private void sendPickup(PlayerEntity player, CallbackInfo ci) { + player.sendPickup((ItemEntity) (Object) this, getStack().getCount()); + } + + /* + @ModifyConstant(method = "setDespawnImmediately", constant = @Constant(intValue = 5999)) + private int setAge(World world) { + return ((IForgeItemStack) stack).getEntityLifespan(((ItemEntity) (Object) this).world) - 1; + } + */ +} diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java index 2c38f304..f23ba83e 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinLivingEntity.java @@ -109,4 +109,21 @@ private float hookApplyDamageForDamageEvent(float damage, DamageSource source) { return EntityEvents.onLivingDamage(entity, source, damage); } + + // TODO: Commented out until LivingDropsEvent is implemented + /* + @Inject(method = "drop", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/entity/LivingEntity;playerHitTimer:I")) + private void beginCaptureDrops(DamageSource source, CallbackInfo ci) { + ((CaptureDropSupplier) this).captureDrops(Lists.newArrayList()); + } + + @Inject(method = "drop", at = @At("TAIL")) + private void beginCaptureDrops(CallbackInfo ci) { + Collection drops = ((CaptureDropSupplier) this).captureDrops(null); + + if (!ForgeHooks.onLivingDrops(this, p_213345_1_, drops, i, recentlyHit > 0)) { + drops.forEach(e -> world.addEntity(e)); + } + } + */ } diff --git a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java index 90bfc860..652af5e6 100644 --- a/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java +++ b/patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinServerPlayerEntity.java @@ -20,14 +20,20 @@ package net.patchworkmc.mixin.event.entity; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeEntity; import net.minecraftforge.event.entity.player.PlayerEvent; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; +import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; import net.patchworkmc.impl.event.entity.EntityEvents; @@ -49,4 +55,11 @@ private void hookCopyFromForCloneEvent(ServerPlayerEntity oldPlayer, boolean ali ServerPlayerEntity speThis = (ServerPlayerEntity) (Object) this; MinecraftForge.EVENT_BUS.post(new PlayerEvent.Clone(speThis, oldPlayer, !alive)); } + + @Inject(method = "dropItem", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD) + private void addToCaptureDrops(ItemStack stack, boolean drop, boolean trace, CallbackInfoReturnable cir, ItemEntity entity) { + if (((IForgeEntity) entity).captureDrops() != null) { + ((IForgeEntity) entity).captureDrops().add(entity); + } + } } diff --git a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json index 7b7c0180..d09d8a23 100644 --- a/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json +++ b/patchwork-events-entity/src/main/resources/patchwork-events-entity.mixins.json @@ -3,6 +3,7 @@ "package": "net.patchworkmc.mixin.event.entity", "compatibilityLevel": "JAVA_8", "mixins": [ + "MixinItemEntity", "MixinEntity", "MixinEntityTrackerEntry", "MixinEntityType", diff --git a/patchwork-extensions-entity/build.gradle b/patchwork-extensions-entity/build.gradle new file mode 100644 index 00000000..ee5ce8bd --- /dev/null +++ b/patchwork-extensions-entity/build.gradle @@ -0,0 +1,2 @@ +archivesBaseName = "patchwork-extensions-entity" +version = getSubprojectVersion(project, "0.1.0") diff --git a/patchwork-extensions-entity/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java b/patchwork-extensions-entity/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java new file mode 100644 index 00000000..a125079f --- /dev/null +++ b/patchwork-extensions-entity/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java @@ -0,0 +1,30 @@ +/* + * Minecraft Forge, Patchwork Project + * Copyright (c) 2016-2020, 2019-2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common.extensions; + +import java.util.Collection; + +import net.minecraft.entity.ItemEntity; + +public interface IForgeEntity { + Collection captureDrops(); + + Collection captureDrops(Collection value); +} diff --git a/patchwork-extensions-entity/src/main/resources/assets/patchwork-extensions-item/icon.png b/patchwork-extensions-entity/src/main/resources/assets/patchwork-extensions-item/icon.png new file mode 100644 index 00000000..de75d2fb Binary files /dev/null and b/patchwork-extensions-entity/src/main/resources/assets/patchwork-extensions-item/icon.png differ diff --git a/patchwork-extensions-entity/src/main/resources/fabric.mod.json b/patchwork-extensions-entity/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..ef112e7a --- /dev/null +++ b/patchwork-extensions-entity/src/main/resources/fabric.mod.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": 1, + "id": "patchwork-extensions-entity", + "name": "Patchwork Entity Extensions", + "version": "${version}", + "description": "Implements the Minecraft Forge extensions API for entities", + "environment": "*", + "license": "LGPL-2.1-only", + "icon": "assets/patchwork-extensions-entity/icon.png", + "contact": { + "issues": "https://github.com/PatchworkMC/patchwork-api/issues", + "sources": "https://github.com/PatchworkMC/patchwork-api" + }, + "authors": [ + "PatchworkMC" + ], + "depends": { + "fabricloader": ">=0.8.4", + "fabric": "*" + }, + "mixins": [ + "patchwork-extensions-entity.mixins.json" + ], + "custom": { + "modmenu:api": true, + "modmenu:parent": "patchwork" + } +} diff --git a/patchwork-extensions-entity/src/main/resources/patchwork-extensions-entity.mixins.json b/patchwork-extensions-entity/src/main/resources/patchwork-extensions-entity.mixins.json new file mode 100644 index 00000000..46ed1bc6 --- /dev/null +++ b/patchwork-extensions-entity/src/main/resources/patchwork-extensions-entity.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "net.patchworkmc.mixin.extensions.entity", + "compatibilityLevel": "JAVA_8", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/settings.gradle b/settings.gradle index 23688998..665af8ba 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,6 +24,7 @@ include 'patchwork-events-rendering' include 'patchwork-events-world' include 'patchwork-extensions' include 'patchwork-extensions-block' +include 'patchwork-extensions-entity' include 'patchwork-extensions-item' include 'patchwork-extensions-shearing' include 'patchwork-fml'