Jump to content

[1.17.1] Multipart Entity interaction


TheOrangeInd

Recommended Posts

Experimenting with multiparty entities, I ran into a problem. My part entity does not detect incoming damage. I was making my entities following the example of vanilla dragon, and I think I missed some important detail. I would be grateful for any hints.

 

So this is my Parent Entity class:

Spoiler

public class EntityTest extends Mob
{
    private final EntityTestPart[] subEntities;
    private final EntityTestPart core;

    protected EntityTest(EntityType<? extends Mob> type, Level level)
    {
        super(type, level);

        core = new EntityTestPart(this, "core", 1.0f, 1.0f);
        subEntities = new EntityTestPart[] {core};
    }

    public static AttributeSupplier.Builder createAttributes()
    {
        return Mob.createMobAttributes()
                .add(Attributes.MAX_HEALTH, 200.0D)
                .add(Attributes.KNOCKBACK_RESISTANCE, 0.95D);
    }

    @Override
    public void checkDespawn() { }

    protected void updateParts()
    {
        for (EntityTestPart part : subEntities)
            movePart(part, 0, 4.5f, 0);
    }

    protected void movePart(EntityTestPart part, double dX, double dY, double dZ)
    {
        Vec3 lastPos = new Vec3(part.getX(), part.getY(), part.getZ());

        part.setPos(this.getX() + dX, this.getY() + dY, this.getZ() + dZ);

        part.xo = lastPos.x;
        part.yo = lastPos.y;
        part.zo = lastPos.z;
        part.xOld = lastPos.x;
        part.yOld = lastPos.y;
        part.zOld = lastPos.z;
    }

    @Override
    public void aiStep()
    {
        super.aiStep();

        updateParts();
    }

    @Override
    public boolean isMultipartEntity() {
        return true;
    }

    @Override
    public net.minecraftforge.entity.PartEntity<?>[] getParts() { return this.subEntities; }

    public void recreateFromPacket(ClientboundAddMobPacket packet)
    {
        super.recreateFromPacket(packet);

        EntityTestPart[] parts = this.getSubEntities();
        for(int i = 0; i < parts.length; ++i)
            parts[i].setId(i + packet.getId());
    }

    public EntityTestPart[] getSubEntities() {
        return this.subEntities;
    }

    @Override
    public boolean isPickable() { return true; }

    @Override
    public Packet<?> getAddEntityPacket() {
        return new ClientboundAddMobPacket(this);
    }
}

 

and a Part Entity:

Spoiler

public class EntityTestPart extends PartEntity<EntityTest>
{
    public final String name;
    private final EntityDimensions size;

    public EntityTestPart(EntityTest parent, String name, float width, float height)
    {
        super(parent);
        this.size = EntityDimensions.scalable(width, height);
        refreshDimensions();
        this.name = name;
    }

    @Override
    public boolean hurt(DamageSource source, float amount)
    {
        System.out.println("HIT");
        return getParent().hurt(source, amount);
    }

    @Override
    public boolean is(Entity entity) {
        return this == entity || this.getParent() == entity;
    }

    @Override
    public EntityDimensions getDimensions(Pose pose) {
        return this.size;
    }

    @Override
    public boolean isPickable() {
        return true;
    }

    @Override
    public boolean shouldBeSaved() {
        return false;
    }

    @Override
    protected void defineSynchedData() { }

    @Override
    protected void readAdditionalSaveData(CompoundTag nbt) { }

    @Override
    protected void addAdditionalSaveData(CompoundTag nbt) { }
}

 

 

Edited by TheOrangeInd
Link to comment
Share on other sites

So, after researching how vanilla projectiles work, I found that when determining whether to hit the target, they request a list of entities using a method from the Level class (the method is called getEntities). So the fact is that in this method they directly check whether the entity is a vanilla Dragon and, if true, request its PartEntities. That is, this method cannot add custom PartEntities to the returned list as ordinary entities, since they do not exist in the world, but they are a logical continuation of the parent class. At the same time, the getEntities method does not ask the checked entity to check the isMultipartEntity (from IForgeEntity interface) and, accordingly, does not add entities returned by the getParts method to the list.

I still do not rule out the possibility that I misunderstand the principle of this system. But at the moment it seems to me that in the current version of Forge, the correct implementation of Multipart Entities in the way conceived by the API developers is not possible.
I will be glad if I'm wrong and someone will correct me.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.