Added custom item entity support via mixin.

This commit is contained in:
Sebastian Hartte
2020-08-03 15:10:25 +02:00
parent 541f07a7e3
commit 63c251294e
9 changed files with 133 additions and 59 deletions
@@ -1,6 +1,5 @@
package appeng.core.sync.packets;
import net.minecraft.entity.EntityType;
import net.minecraft.network.PacketByteBuf;
public interface ICustomEntity {
@@ -24,10 +24,14 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;
public abstract class AEBaseItemEntity extends ItemEntity {
import appeng.core.sync.packets.ICustomEntity;
import appeng.core.sync.packets.SpawnEntityPacket;
public abstract class AEBaseItemEntity extends ItemEntity implements ICustomEntity {
protected AEBaseItemEntity(EntityType<? extends AEBaseItemEntity> entityType, final World world) {
super(entityType, world);
@@ -48,4 +52,9 @@ public abstract class AEBaseItemEntity extends ItemEntity {
return this.world.getOtherEntities(this, region);
}
@Override
public Packet<?> createSpawnPacket() {
return SpawnEntityPacket.create(this);
}
}
@@ -38,7 +38,6 @@ import appeng.api.features.AEFeature;
import appeng.client.render.effects.ParticleTypes;
import appeng.core.AEConfig;
import appeng.core.Api;
import appeng.core.AppEng;
import appeng.util.Platform;
public final class ChargedQuartzEntity extends AEBaseItemEntity {
@@ -0,0 +1,16 @@
package appeng.hooks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
public interface AECustomEntityItem {
/**
* @return Either a new entity (not added to the world yet), or the original one
* to keep it.
*/
Entity replaceItemEntity(ServerWorld world, ItemEntity itemEntity, ItemStack itemStack);
}
@@ -24,13 +24,15 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
@@ -45,12 +47,14 @@ import appeng.api.implementations.items.IUpgradeModule;
import appeng.api.implementations.tiles.ISegmentedInventory;
import appeng.api.parts.IPartHost;
import appeng.api.parts.SelectedPart;
import appeng.hooks.AECustomEntityItem;
import appeng.hooks.AEToolItem;
import appeng.items.AEBaseItem;
import appeng.util.InventoryAdaptor;
import appeng.util.inv.AdaptorFixedInv;
public final class MaterialItem extends AEBaseItem implements IStorageComponent, IUpgradeModule, AEToolItem {
public final class MaterialItem extends AEBaseItem
implements IStorageComponent, IUpgradeModule, AEToolItem, AECustomEntityItem {
/**
* NBT property used by the name press to store the name to be inscribed.
@@ -147,31 +151,30 @@ public final class MaterialItem extends AEBaseItem implements IStorageComponent,
return ActionResult.PASS;
}
// FIXME FABRIC @Override
// FIXME FABRIC public boolean hasCustomEntity(final ItemStack is) {
// FIXME FABRIC return materialType.hasCustomEntity();
// FIXME FABRIC }
@Override
public Entity replaceItemEntity(ServerWorld world, ItemEntity itemEntity, ItemStack itemStack) {
if (!materialType.hasCustomEntity()) {
return itemEntity;
}
// FIXME FABRIC @Override
// FIXME FABRIC public Entity createEntity(final World w, final Entity location, final ItemStack itemstack) {
// FIXME FABRIC final Class<? extends Entity> droppedEntity = materialType.getCustomEntityClass();
// FIXME FABRIC final Entity eqi;
final Class<? extends Entity> droppedEntity = materialType.getCustomEntityClass();
final Entity eqi;
// FIXME FABRIC try {
// FIXME FABRIC eqi = droppedEntity.getConstructor(World.class, double.class, double.class, double.class, ItemStack.class)
// FIXME FABRIC .newInstance(w, location.getX(), location.getY(), location.getZ(), itemstack);
// FIXME FABRIC } catch (final Throwable t) {
// FIXME FABRIC throw new IllegalStateException(t);
// FIXME FABRIC }
try {
eqi = droppedEntity.getConstructor(World.class, double.class, double.class, double.class, ItemStack.class)
.newInstance(world, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), itemStack);
} catch (final Throwable t) {
throw new IllegalStateException(t);
}
// FIXME FABRIC eqi.setVelocity(location.getVelocity());
eqi.setVelocity(itemEntity.getVelocity());
// FIXME FABRIC if (location instanceof ItemEntity && eqi instanceof ItemEntity) {
// FIXME FABRIC ((ItemEntity) eqi).setDefaultPickupDelay();
// FIXME FABRIC }
if (eqi instanceof ItemEntity) {
((ItemEntity) eqi).setToDefaultPickupDelay();
}
// FIXME FABRIC return eqi;
// FIXME FABRIC }
return eqi;
}
@Override
public int getBytes(final ItemStack is) {
@@ -29,10 +29,13 @@ import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.Material;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.collection.DefaultedList;
@@ -41,13 +44,15 @@ import net.minecraft.world.World;
import appeng.api.implementations.items.IGrowableCrystal;
import appeng.core.localization.ButtonToolTips;
import appeng.entity.GrowingCrystalEntity;
import appeng.hooks.AECustomEntityItem;
import appeng.items.AEBaseItem;
/**
* This item reprents one of the seeds used to grow various forms of quartz by
* throwing them into water (for that behavior, see the linked entity)
*/
public class CrystalSeedItem extends AEBaseItem implements IGrowableCrystal {
public class CrystalSeedItem extends AEBaseItem implements IGrowableCrystal, AECustomEntityItem {
/**
* Name of NBT tag used to store the growth progress value.
@@ -111,25 +116,19 @@ public class CrystalSeedItem extends AEBaseItem implements IGrowableCrystal {
return new LiteralText(Math.round(100 * progress / (float) GROWTH_TICKS_REQUIRED) + "%");
}
// FIXME FABRIC Needs custom mixin
// FIXME FABRIC @Override
// FIXME FABRIC public boolean hasCustomEntity(final ItemStack stack) {
// FIXME FABRIC return true;
// FIXME FABRIC }
// FIXME FABRIC
// FIXME FABRIC @Override
// FIXME FABRIC public Entity createEntity(final World world, final Entity location, final ItemStack itemstack) {
// FIXME FABRIC final GrowingCrystalEntity egc = new GrowingCrystalEntity(world, location.getX(), location.getY(),
// FIXME FABRIC location.getZ(), itemstack);
// FIXME FABRIC
// FIXME FABRIC egc.setVelocity(location.getVelocity());
// FIXME FABRIC
// FIXME FABRIC // Cannot read the pickup delay of the original item, so we
// FIXME FABRIC // use the pickup delay used for items dropped by a player instead
// FIXME FABRIC egc.setPickupDelay(40);
// FIXME FABRIC
// FIXME FABRIC return egc;
// FIXME FABRIC }
@Override
public Entity replaceItemEntity(ServerWorld world, ItemEntity itemEntity, ItemStack itemStack) {
final GrowingCrystalEntity egc = new GrowingCrystalEntity(world, itemEntity.getX(), itemEntity.getY(),
itemEntity.getZ(), itemStack);
egc.setVelocity(itemEntity.getVelocity());
// Cannot read the pickup delay of the original item, so we
// use the pickup delay used for items dropped by a player instead
egc.setPickupDelay(40);
return egc;
}
@Override
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> items) {
@@ -0,0 +1,45 @@
package appeng.mixins;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import appeng.hooks.AECustomEntityItem;
/**
* This Mixin will replace newly spawned ItemEntities with custom entities if
* the item wants it. This is not applied retroactively to entities that are
* already spawned and just re-added to the world when a chunk is loaded.
*/
@Mixin(value = ServerWorld.class, priority = 9999)
public class ServerWorldCustomItemEntityMixin {
@SuppressWarnings("ConstantConditions")
@ModifyVariable(method = { "spawnEntity" }, at = @At("HEAD"), argsOnly = true)
public Entity onSpawnEntity(Entity entity) {
if (entity instanceof ItemEntity) {
ItemEntity itemEntity = (ItemEntity) entity;
ItemStack stack = itemEntity.getStack();
if (stack == null) {
return entity;
}
Item item = stack.getItem();
if (item instanceof AECustomEntityItem) {
ServerWorld self = (ServerWorld) (Object) this;
entity = ((AECustomEntityItem) item).replaceItemEntity(self, itemEntity, stack);
if (entity != itemEntity) {
// Item may actually want to keep the original
itemEntity.remove();
}
}
}
return entity;
}
}
@@ -62,6 +62,7 @@ import appeng.container.ContainerOpener;
import appeng.container.implementations.FormationPlaneContainer;
import appeng.core.AEConfig;
import appeng.core.Api;
import appeng.hooks.AECustomEntityItem;
import appeng.items.parts.PartModels;
import appeng.me.GridAccessException;
import appeng.me.storage.MEInventoryHandler;
@@ -203,6 +204,11 @@ public class FormationPlanePart extends AbstractFormationPlanePart<IAEItemStack>
final BlockEntity te = this.getHost().getTile();
final World w = te.getWorld();
if (!(w instanceof ServerWorld)) {
return input;
}
ServerWorld serverWorld = (ServerWorld) w;
final AEPartLocation side = this.getSide();
final BlockPos placePos = te.getPos().offset(side.getFacing());
@@ -210,7 +216,7 @@ public class FormationPlanePart extends AbstractFormationPlanePart<IAEItemStack>
if (w.getBlockState(placePos).getMaterial().isReplaceable()) {
if (placeBlock == YesNo.YES && (i instanceof BlockItem || i instanceof FireworkChargeItem
|| i instanceof FireworkItem || i instanceof IPartItem)) {
final PlayerEntity player = FakePlayer.getOrCreate((ServerWorld) w);
final PlayerEntity player = FakePlayer.getOrCreate(serverWorld);
Platform.configurePlayer(player, side, this.getTile());
Hand hand = player.getActiveHand();
player.setStackInHand(hand, is);
@@ -279,20 +285,17 @@ public class FormationPlanePart extends AbstractFormationPlanePart<IAEItemStack>
+ .5 + te.getPos().getZ();
final ItemEntity ei = new ItemEntity(w, x, y, z, is.copy());
Entity result = ei;
ei.setVelocity(side.xOffset * 0.2, side.yOffset * 0.2, side.zOffset * 0.2);
// FIXME FABRIC No custom item entity support
// FIXME FABRIC if (is.getItem().hasCustomEntity(is)) {
// FIXME FABRIC result = is.getItem().createEntity(w, ei, is);
// FIXME FABRIC if (result != null) {
// FIXME FABRIC ei.remove();
// FIXME FABRIC } else {
// FIXME FABRIC result = ei;
// FIXME FABRIC }
// FIXME FABRIC }
Entity result;
if (is.getItem() instanceof AECustomEntityItem) {
result = ((AECustomEntityItem) is.getItem()).replaceItemEntity(serverWorld, ei, is);
if (result != ei) {
ei.remove();
}
} else {
result = ei;
}
if (!w.spawnEntity(result)) {
result.remove();