diff --git a/patches/minecraft/net/minecraft/server/level/ServerLevel.java.patch b/patches/minecraft/net/minecraft/server/level/ServerLevel.java.patch index 653b5643d3..187ce77e8e 100644 --- a/patches/minecraft/net/minecraft/server/level/ServerLevel.java.patch +++ b/patches/minecraft/net/minecraft/server/level/ServerLevel.java.patch @@ -1,7 +1,11 @@ --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -173,6 +_,7 @@ - final Int2ObjectMap f_143247_ = new Int2ObjectOpenHashMap<>(); +@@ -170,9 +_,10 @@ + private final List f_8558_; + @Nullable + private final EndDragonFight f_8559_; +- final Int2ObjectMap f_143247_ = new Int2ObjectOpenHashMap<>(); ++ final Int2ObjectMap> f_143247_ = new Int2ObjectOpenHashMap<>(); private final StructureFeatureManager f_8560_; private final boolean f_8561_; + private net.minecraftforge.common.util.WorldCapabilityData capabilityData; @@ -199,16 +203,38 @@ explosion.m_46061_(); explosion.m_46075_(false); if (p_8661_ == Explosion.BlockInteraction.NONE) { -@@ -1355,6 +_,12 @@ - BlockPos.m_121976_(i - 2, j, k - 2, i + 2, j, k + 2).forEach((p_143260_) -> { - p_8618_.m_46597_(p_143260_, Blocks.f_50080_.m_49966_()); +@@ -1357,6 +_,12 @@ }); -+ } -+ + } + + protected void initCapabilities() { + this.gatherCapabilities(); + capabilityData = this.m_8895_().m_164861_(e -> net.minecraftforge.common.util.WorldCapabilityData.load(e, getCapabilities()), () -> new net.minecraftforge.common.util.WorldCapabilityData(getCapabilities()), net.minecraftforge.common.util.WorldCapabilityData.ID); + capabilityData.setCapabilities(getCapabilities()); - } - ++ } ++ public LevelEntityGetter m_142646_() { + return this.f_143244_.m_157567_(); + } +@@ -1422,8 +_,8 @@ + ServerLevel.this.f_143246_.add((Mob)p_143371_); + } + +- if (p_143371_ instanceof EnderDragon) { +- for(EnderDragonPart enderdragonpart : ((EnderDragon)p_143371_).m_31156_()) { ++ if (p_143371_.isMultipartEntity()) { ++ for(net.minecraftforge.entity.PartEntity enderdragonpart : p_143371_.getParts()) { + ServerLevel.this.f_143247_.put(enderdragonpart.m_142049_(), enderdragonpart); + } + } +@@ -1442,8 +_,8 @@ + ServerLevel.this.f_143246_.remove(p_143375_); + } + +- if (p_143375_ instanceof EnderDragon) { +- for(EnderDragonPart enderdragonpart : ((EnderDragon)p_143375_).m_31156_()) { ++ if (p_143375_.isMultipartEntity()) { ++ for(net.minecraftforge.entity.PartEntity enderdragonpart : p_143375_.getParts()) { + ServerLevel.this.f_143247_.remove(enderdragonpart.m_142049_()); + } + } diff --git a/patches/minecraft/net/minecraft/world/level/Level.java.patch b/patches/minecraft/net/minecraft/world/level/Level.java.patch index dc5d86d69c..0bab988397 100644 --- a/patches/minecraft/net/minecraft/world/level/Level.java.patch +++ b/patches/minecraft/net/minecraft/world/level/Level.java.patch @@ -182,6 +182,28 @@ } public boolean m_46749_(BlockPos p_46750_) { +@@ -530,8 +_,8 @@ + list.add(p_151522_); + } + +- if (p_151522_ instanceof EnderDragon) { +- for(EnderDragonPart enderdragonpart : ((EnderDragon)p_151522_).m_31156_()) { ++ if (p_151522_.isMultipartEntity()) { ++ for(net.minecraftforge.entity.PartEntity enderdragonpart : p_151522_.getParts()) { + if (p_151522_ != p_46536_ && p_46538_.test(enderdragonpart)) { + list.add(enderdragonpart); + } +@@ -550,8 +_,8 @@ + list.add(p_151539_); + } + +- if (p_151539_ instanceof EnderDragon) { +- for(EnderDragonPart enderdragonpart : ((EnderDragon)p_151539_).m_31156_()) { ++ if (p_151539_.isMultipartEntity()) { ++ for(net.minecraftforge.entity.PartEntity enderdragonpart : p_151539_.getParts()) { + T t = p_151528_.m_141992_(enderdragonpart); + if (t != null && p_151530_.test(t)) { + list.add(t); @@ -571,6 +_,7 @@ this.m_46745_(p_151544_).m_6427_(); } diff --git a/src/test/java/net/minecraftforge/debug/entity/PartEntityTest.java b/src/test/java/net/minecraftforge/debug/entity/PartEntityTest.java new file mode 100644 index 0000000000..d374b7c8e3 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/entity/PartEntityTest.java @@ -0,0 +1,210 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * 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.debug.entity; + +import net.minecraft.client.renderer.entity.PigRenderer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAddMobPacket; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.entity.PartEntity; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fmllegacy.RegistryObject; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +@Mod(value = PartEntityTest.MOD_ID) +public class PartEntityTest +{ + static final String MOD_ID = "part_entity_test"; + static final boolean ENABLED = true; + + private static final DeferredRegister> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITIES, MOD_ID); + private static final RegistryObject> TEST_ENTITY = ENTITIES.register("test_entity", () -> EntityType.Builder.of(TestEntity::new, MobCategory.CREATURE).sized(16.0F, 8.0F).clientTrackingRange(10).build("test_entity")); + + public PartEntityTest() + { + if (ENABLED) + { + ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus()); + FMLJavaModLoadingContext.get().getModEventBus().register(this); + } + } + + @SubscribeEvent + public void onRegisterAttributes(final EntityAttributeCreationEvent event) + { + event.put(TEST_ENTITY.get(), Pig.createAttributes().build()); + } + + @Mod.EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) + private static class ClientEvents + { + @SubscribeEvent + public static void onRegisterRenderers(final EntityRenderersEvent.RegisterRenderers event) + { + if (!ENABLED) return; + + event.registerEntityRenderer(TEST_ENTITY.get(), PigRenderer::new); + } + } + + private static class TestEntity extends Pig + { + private final TestEntityPart[] subEntities; + public final TestEntityPart head; + private final TestEntityPart neck; + private final TestEntityPart body; + private final TestEntityPart tail1; + private final TestEntityPart tail2; + private final TestEntityPart tail3; + private final TestEntityPart wing1; + private final TestEntityPart wing2; + + public TestEntity(EntityType entity, Level world) + { + super(entity, world); + this.head = new TestEntityPart(this, 1.0F, 1.0F); + this.neck = new TestEntityPart(this, 3.0F, 3.0F); + this.body = new TestEntityPart(this, 5.0F, 3.0F); + this.tail1 = new TestEntityPart(this, 2.0F, 2.0F); + this.tail2 = new TestEntityPart(this, 2.0F, 2.0F); + this.tail3 = new TestEntityPart(this, 2.0F, 2.0F); + this.wing1 = new TestEntityPart(this, 4.0F, 2.0F); + this.wing2 = new TestEntityPart(this, 4.0F, 2.0F); + this.subEntities = new TestEntityPart[]{this.head, this.neck, this.body, this.tail1, this.tail2, this.tail3, this.wing1, this.wing2}; + } + + @Override + public void aiStep() + { + super.aiStep(); + + for (TestEntityPart part : this.subEntities) + { + part.setPos(this.getX(), this.getY(), this.getZ()); + } + + Vec3[] vec3 = new Vec3[this.subEntities.length]; + for(int j = 0; j < this.subEntities.length; ++j) + { + vec3[j] = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), this.subEntities[j].getZ()); + } + + for(int l = 0; l < this.subEntities.length; ++l) + { + this.subEntities[l].xo = vec3[l].x; + this.subEntities[l].yo = vec3[l].y; + this.subEntities[l].zo = vec3[l].z; + this.subEntities[l].xOld = vec3[l].x; + this.subEntities[l].yOld = vec3[l].y; + this.subEntities[l].zOld = vec3[l].z; + } + } + + @Override + public boolean isMultipartEntity() + { + return true; + } + + @Override + public PartEntity[] getParts() + { + return this.subEntities; + } + + @Override + public void recreateFromPacket(ClientboundAddMobPacket packet) + { + super.recreateFromPacket(packet); + PartEntity[] parts = this.getParts(); + + for(int i = 0; i < parts.length; ++i) + { + parts[i].setId(i + packet.getId()); + } + + } + } + + private static class TestEntityPart extends PartEntity + { + public final TestEntity parent; + private final EntityDimensions size; + + public TestEntityPart(TestEntity parent, float width, float height) + { + super(parent); + this.size = EntityDimensions.scalable(width, height); + this.refreshDimensions(); + this.parent = parent; + } + + protected void defineSynchedData() {} + + protected void readAdditionalSaveData(CompoundTag nbt) {} + + protected void addAdditionalSaveData(CompoundTag nbt) {} + + public boolean isPickable() + { + return true; + } + + public boolean hurt(DamageSource source, float amount) + { + return !this.isInvulnerableTo(source) && this.parent.hurt(source, amount); + } + + public boolean is(Entity entity) + { + return this == entity || this.parent == entity; + } + + public Packet getAddEntityPacket() + { + throw new UnsupportedOperationException(); + } + + public EntityDimensions getDimensions(Pose matrix) + { + return this.size; + } + + public boolean shouldBeSaved() + { + return false; + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 3d2b7ede92..cd863b5cd9 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -168,5 +168,7 @@ license="LGPL v2.1" modId="custom_tooltip_test" [[mods]] modId="full_pots_accessor_demo" +[[mods]] + modId="part_entity_test" # ADD ABOVE THIS LINE