Added custom item entity support via mixin.
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user