- 74
- 2
Пытаюсь сделать кастомного моба, который должен получать повреждения отдельно по разным частям тела. Для начал решил добавить ему второй хитбокс в районе головы. В качестве примера использовал ванильного дракона (он имеет определенный список сущностей-частей, которые позволяют наносить родительскому мобу урон по разным частям тела). Я сделал подобный класс сущности-части. Проблема в том, что я не понимаю, как правильно ее добавить в мир. Если сделать так же, как в ваниле (создавать экземпляр класса части без непосредственно спавна методом addEntity() класса World), сущность в мире не появится (я проверял ее координаты, и она находилась там, где и нужно, но ее хитбокса не было видно и взаимодействовать с ним я не мог). Я так понимаю, что тут дело в том, как forge регистрирует сущности. Но, в таком случае, как правильно создать сущность, состоящую из множества частей, которые будут иметь EntityType своего родителя? Буду благодарен за любые прояснения в этом вопросе.
Класс родительского Entity (код, не касающийся вопроса, вырезан):
Код класса EntityPart:
Класс родительского Entity (код, не касающийся вопроса, вырезан):
Java:
public class EntityFowler extends ZombieEntity
{
private byte meleeAttackTimer;
private final EntityPart[] bodyParts;
private final EntityPart headEntity;
public EntityFowler(EntityType<? extends ZombieEntity> type, World worldIn)
{
super(type, worldIn);
headEntity = new EntityPart(this, "head", 0.7f, 0.7f);
bodyParts = new EntityPart[] { headEntity };
}
@Override
public void livingTick()
{
setPartPosition(headEntity, 0, 0.6f, 0);
super.livingTick();
}
private void setPartPosition(EntityPart part, double offsetX, double offsetY, double offsetZ)
{
//System.out.println(part.getPosX() + " " + part.getPosY() + " " + part.getPosZ());
part.setPosition(this.getPosX() + offsetX, this.getPosY() + offsetY, this.getPosZ() + offsetZ);
}
}
Код класса EntityPart:
Java:
public class EntityPart extends Entity
{
public final String name;
public final LivingEntity parent;
private final EntitySize size;
private boolean isCollidable = true;
public EntityPart(LivingEntity parentEntity, String name, float width, float height) { this(parentEntity, name, width, height, true); }
public EntityPart(LivingEntity parentEntity, String name, float width, float height, boolean isCollidable)
{
super(parentEntity.getType(), parentEntity.getEntityWorld());
this.size = EntitySize.flexible(width, height);
this.recalculateSize();
this.parent = parentEntity;
this.name = name;
this.isCollidable = isCollidable;
}
@Override
public boolean canBeCollidedWith() { return true; }
public void setCollidable(boolean value) { isCollidable = value; }
@Override
public boolean attackEntityFrom(DamageSource source, float amount)
{
if(parent instanceof IMultipartEntity) return ((IMultipartEntity)parent).attackEntityPartFrom(this, source, amount);
return !this.isInvulnerableTo(source) && this.parent.attackEntityFrom(source, amount);
}
@Override
protected void registerData() { }
@Override
protected void readAdditional(CompoundNBT compound){}
@Override
protected void writeAdditional(CompoundNBT compound){}
@Override
public IPacket<?> createSpawnPacket()
{
//return NetworkHooks.getEntitySpawningPacket(this);
throw new UnsupportedOperationException();
}
@Override
public boolean isEntityEqual(Entity entityIn) { return entityIn == this || entityIn == parent; }
@Override
public EntitySize getSize(Pose pose) { return size; }
@Override
public ActionResultType applyPlayerInteraction(PlayerEntity player, Vector3d vec, Hand hand)
{
return super.applyPlayerInteraction(player, vec, hand);
}
}