diff --git a/src/main/java/eu/midnightdust/motschen/decorative/entity/BathTireEntity.java b/src/main/java/eu/midnightdust/motschen/decorative/entity/BathTireEntity.java index 2d8aa58..f000db7 100755 --- a/src/main/java/eu/midnightdust/motschen/decorative/entity/BathTireEntity.java +++ b/src/main/java/eu/midnightdust/motschen/decorative/entity/BathTireEntity.java @@ -1,5 +1,8 @@ package eu.midnightdust.motschen.decorative.entity; +import eu.midnightdust.motschen.decorative.polymer.entity.ItemDisplayBasedEntity; +import eu.pb4.polymer.virtualentity.api.elements.ItemDisplayElement; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.MobEntity; @@ -14,10 +17,12 @@ import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.joml.Vector3f; -public class BathTireEntity extends MobEntity { +public class BathTireEntity extends MobEntity implements ItemDisplayBasedEntity { public BathTireEntity(EntityType entityType, World world) { super(entityType, world); + this.onCreated(this); } @Override @@ -26,7 +31,7 @@ public class BathTireEntity extends MobEntity { if (player.isSneaking()) { this.remove(RemovalReason.DISCARDED); System.out.println(Identifier.tryParse(this.getType().getUntranslatedName())); - player.setStackInHand(hand, new ItemStack(Registries.ITEM.get(Identifier.tryParse("decorative:" + this.getType().getUntranslatedName())))); + player.setStackInHand(hand, getItemStackForType()); return ActionResult.SUCCESS; } else if (!player.isSneaking()) { @@ -57,4 +62,25 @@ public class BathTireEntity extends MobEntity { public boolean canWalkOnFluid(FluidState fluid) { return true; } + private ItemStack getItemStackForType() { + return new ItemStack(Registries.ITEM.get(Identifier.tryParse("decorative:" + this.getType().getUntranslatedName()))); + } + + // Polymer + @Override + public ItemStack getVisualItemStack() { + return getItemStackForType(); + } + @Override + public void setItemDisplayProperties(ItemDisplayElement display) { + display.setInvisible(false); + display.setModelTransformation(ModelTransformationMode.HEAD); + display.setTeleportDuration(3); + display.setScale(new Vector3f(1f)); + display.setTranslation(new Vector3f(0, 0.4f, 0)); + } + @Override + public Vec3d getClientSidePosition(Vec3d vec3d) { + return vec3d.add(0, -1.5d, 0); + } } diff --git a/src/main/java/eu/midnightdust/motschen/decorative/entity/BeachBallEntity.java b/src/main/java/eu/midnightdust/motschen/decorative/entity/BeachBallEntity.java index 0913a3b..9f38215 100755 --- a/src/main/java/eu/midnightdust/motschen/decorative/entity/BeachBallEntity.java +++ b/src/main/java/eu/midnightdust/motschen/decorative/entity/BeachBallEntity.java @@ -1,6 +1,9 @@ package eu.midnightdust.motschen.decorative.entity; import eu.midnightdust.motschen.decorative.init.Pool; +import eu.midnightdust.motschen.decorative.polymer.entity.ItemDisplayBasedEntity; +import eu.pb4.polymer.virtualentity.api.elements.ItemDisplayElement; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.entity.EntityType; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; @@ -12,10 +15,12 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.joml.Vector3f; -public class BeachBallEntity extends MobEntity { +public class BeachBallEntity extends MobEntity implements ItemDisplayBasedEntity { public BeachBallEntity(EntityType entityType, World world) { super(entityType, world); + this.onCreated(this); } @Override @@ -41,4 +46,25 @@ public class BeachBallEntity extends MobEntity { public boolean canWalkOnFluid(FluidState fluid) { return true; } + // Polymer + @Override + public ItemStack getVisualItemStack() { + return new ItemStack(Pool.BEACH_BALL_ITEM); + } + @Override + public void setItemDisplayProperties(ItemDisplayElement display) { + display.setInvisible(false); + display.setModelTransformation(ModelTransformationMode.HEAD); + display.setTeleportDuration(3); + display.setScale(new Vector3f(1f)); + display.setTranslation(new Vector3f(0, -0.4f, 0)); + } + @Override + public Vec3d getClientSidePosition(Vec3d vec3d) { + return vec3d.add(0, 0.25d, 0); + } + @Override + public boolean isSmall() { + return true; + } } diff --git a/src/main/java/eu/midnightdust/motschen/decorative/item/BathTireItem.java b/src/main/java/eu/midnightdust/motschen/decorative/item/BathTireItem.java index 7d2c5b5..6a86c33 100755 --- a/src/main/java/eu/midnightdust/motschen/decorative/item/BathTireItem.java +++ b/src/main/java/eu/midnightdust/motschen/decorative/item/BathTireItem.java @@ -2,14 +2,12 @@ package eu.midnightdust.motschen.decorative.item; import eu.pb4.factorytools.api.item.AutoModeledPolymerItem; import net.minecraft.block.FluidBlock; -import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnReason; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; import net.minecraft.stat.Stats; import net.minecraft.util.Hand; @@ -21,7 +19,7 @@ import net.minecraft.world.RaycastContext; import net.minecraft.world.World; public class BathTireItem extends Item implements AutoModeledPolymerItem { - private final EntityType type; + public final EntityType type; public BathTireItem(EntityType type, Item.Settings settings) { super(settings); @@ -41,8 +39,7 @@ public class BathTireItem extends Item implements AutoModeledPolymerItem { if (!(world.getBlockState(blockPos).getBlock() instanceof FluidBlock)) { return TypedActionResult.pass(itemStack); } else if (world.canPlayerModifyAt(user, blockPos) && user.canPlaceOn(blockPos, hitResult.getSide(), itemStack)) { - EntityType entityType = this.getEntityType(itemStack.getComponents().get(DataComponentTypes.ENTITY_DATA).copyNbt()); - if (entityType.spawnFromItemStack((ServerWorld) world, itemStack, user, blockPos.up(1), SpawnReason.SPAWN_EGG, false, false) == null) { + if (this.type.spawnFromItemStack((ServerWorld) world, itemStack, user, blockPos.up(1), SpawnReason.SPAWN_EGG, false, false) == null) { return TypedActionResult.pass(itemStack); } else { if (!user.getAbilities().creativeMode) { @@ -58,17 +55,6 @@ public class BathTireItem extends Item implements AutoModeledPolymerItem { } } - public EntityType getEntityType(NbtCompound tag) { - if (tag != null && tag.contains("EntityTag", 10)) { - NbtCompound compoundTag = tag.getCompound("EntityTag"); - if (compoundTag.contains("id", 8)) { - return EntityType.get(compoundTag.getString("id")).orElse(this.type); - } - } - - return this.type; - } - @Override public Item getPolymerItem() { return Items.DRIED_KELP; diff --git a/src/main/java/eu/midnightdust/motschen/decorative/mixin/ArmorStandEntityAccessor.java b/src/main/java/eu/midnightdust/motschen/decorative/mixin/ArmorStandEntityAccessor.java new file mode 100644 index 0000000..c733adb --- /dev/null +++ b/src/main/java/eu/midnightdust/motschen/decorative/mixin/ArmorStandEntityAccessor.java @@ -0,0 +1,14 @@ +package eu.midnightdust.motschen.decorative.mixin; + +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.decoration.ArmorStandEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ArmorStandEntity.class) +public interface ArmorStandEntityAccessor { + @Accessor + static TrackedData getARMOR_STAND_FLAGS() { + throw new RuntimeException(); + } +} diff --git a/src/main/java/eu/midnightdust/motschen/decorative/polymer/entity/ItemDisplayBasedEntity.java b/src/main/java/eu/midnightdust/motschen/decorative/polymer/entity/ItemDisplayBasedEntity.java new file mode 100644 index 0000000..627a934 --- /dev/null +++ b/src/main/java/eu/midnightdust/motschen/decorative/polymer/entity/ItemDisplayBasedEntity.java @@ -0,0 +1,94 @@ +package eu.midnightdust.motschen.decorative.polymer.entity; + +import eu.midnightdust.motschen.decorative.mixin.ArmorStandEntityAccessor; +import eu.pb4.polymer.core.api.entity.PolymerEntity; +import eu.pb4.polymer.virtualentity.api.ElementHolder; +import eu.pb4.polymer.virtualentity.api.VirtualEntityUtils; +import eu.pb4.polymer.virtualentity.api.attachment.EntityAttachment; +import eu.pb4.polymer.virtualentity.api.elements.ItemDisplayElement; +import eu.pb4.polymer.virtualentity.api.tracker.EntityTrackedData; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.item.ItemStack; +import net.minecraft.server.network.ServerPlayerEntity; +import org.joml.Vector3f; + +import java.util.List; +import java.util.WeakHashMap; + +public interface ItemDisplayBasedEntity extends PolymerEntity { + WeakHashMap DISPLAY_ELEMENTS = new WeakHashMap<>(); + + ItemStack getVisualItemStack(); + + // This needs to be called on entity init + default void onCreated(LivingEntity entity) { + ElementHolder holder = new ElementHolder(); + + ItemDisplayElement display = initDisplayEntity(); + holder.addElement(display); + DISPLAY_ELEMENTS.put(entity, display); + + EntityAttachment.of(holder, entity); + VirtualEntityUtils.addVirtualPassenger(entity, display.getEntityId()); + } + default ItemDisplayElement initDisplayEntity() { + ItemDisplayElement display = new ItemDisplayElement(getVisualItemStack()); + setItemDisplayProperties(display); + return display; + } + default void setItemDisplayProperties(ItemDisplayElement display) { + display.setInvisible(false); + display.setModelTransformation(ModelTransformationMode.HEAD); + display.setTeleportDuration(3); + display.setScale(new Vector3f(1f)); + } + default boolean isSmall() { + return false; + } + @Override + default float getClientSideYaw(float yaw) { + if (DISPLAY_ELEMENTS.containsKey((LivingEntity) this)) { + DISPLAY_ELEMENTS.get((LivingEntity) this).setYaw(yaw); + } + return yaw; + } + + @Override + default float getClientSidePitch(float pitch) { + if (DISPLAY_ELEMENTS.containsKey((LivingEntity) this)) { + DISPLAY_ELEMENTS.get((LivingEntity) this).setPitch(pitch); + } + return pitch; + } + + @Override + default EntityType getPolymerEntityType(ServerPlayerEntity player) { + return EntityType.ARMOR_STAND; + } + @Override + default void modifyRawTrackedData(List> data, ServerPlayerEntity player, boolean initial) { + setInvisible(data, true); + if (isSmall()) data.add(DataTracker.SerializedEntry.of(ArmorStandEntityAccessor.getARMOR_STAND_FLAGS(), (byte) (0b00000011))); + } + + static void setInvisible(List> data, boolean invisible) { + setFlag(data, EntityTrackedData.FLAGS, EntityTrackedData.INVISIBLE_FLAG_INDEX, invisible); + } + static void setFlag(List> data, TrackedData type, int index, boolean value) { + // More elegant code that doesn't work somehow + //var flagsData = data.stream().filter(serializedEntry -> serializedEntry.handler().equals(type.dataType())).findFirst(); + //byte b = flagsData.isEmpty() ? 0 : (byte) flagsData.get().value(); + //flagsData.ifPresent(data::remove); + byte b = 0; + if (value) { + data.add(DataTracker.SerializedEntry.of(type, (byte) (b | 1 << index))); + } else { + data.add(DataTracker.SerializedEntry.of(type, (byte) (b & ~(1 << index)))); + } + + } +} diff --git a/src/main/resources/decorative.mixins.json b/src/main/resources/decorative.mixins.json new file mode 100644 index 0000000..1da59f8 --- /dev/null +++ b/src/main/resources/decorative.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "eu.midnightdust.motschen.decorative.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "ArmorStandEntityAccessor" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 60fb3b2..966ea45 100755 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -28,6 +28,10 @@ ] }, + "mixins": [ + "decorative.mixins.json" + ], + "depends": { "fabric": "*", "midnightlib": "*"