Posted October 18, 20204 yr Version: 1.15.2 I'm trying to make a mob that has multiple hitboxes, i take a look on Ender Dragon's code but when i hit the entity, it just dont works. (in debug mode(f3) it shows me the hitboxes correctly) NewEntity.class public class NewEntity extends MultiPartEntity { protected final MultiPartEntityPart[] bodyParts; public final MultiPartEntityPart headPart; public final MultiPartEntityPart bodyPart; public NewEntity(EntityType<? extends MultiPartEntity> type, World worldIn) { super(type, worldIn); this.bodyPart = new MultiPartEntityPart(this, "body", 2.0F, 1.0F); this.headPart = new MultiPartEntityPart(this, "head", 1.0F, 1.0F); this.bodyParts = new MultiPartEntityPart[]{this.headPart,this.bodyPart}; } @Override protected void registerAttributes() { super.registerAttributes(); this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(100); } public boolean attackEntityFrom(DamageSource source, float amount) { return false; } public boolean attackEntityFrom(MultiPartEntityPart entityPart, DamageSource source, float damage) { System.out.println(entityPart.partName); return true; } public boolean canBeCollidedWith() { return false; } @Override public boolean canBePushed() { return false; } @Override public void livingTick() { super.livingTick(); Vec3d[] avec3d = new Vec3d[this.bodyParts.length]; for(int j = 0; j < this.bodyParts.length; ++j) { avec3d[j] = new Vec3d(this.bodyParts[j].getPosX(), this.bodyParts[j].getPosY(), this.bodyParts[j].getPosZ()); } bodyParts[0].setPosition(0,0 + 1f,0); bodyParts[1].setPosition(0,0 - 0.2f,0); for(int l = 0; l < this.bodyParts.length; ++l) { this.bodyParts[l].prevPosX = avec3d[l].x; this.bodyParts[l].prevPosY = avec3d[l].y; this.bodyParts[l].prevPosZ = avec3d[l].z; this.bodyParts[l].lastTickPosX = avec3d[l].x; this.bodyParts[l].lastTickPosY = avec3d[l].y; this.bodyParts[l].lastTickPosZ = avec3d[l].z; } } @Override public MultiPartEntityPart[] getAllParts() { return this.bodyParts; } } MultiPartEntity.class public abstract class MultiPartEntity extends CreatureEntity { protected MultiPartEntity(EntityType<? extends CreatureEntity> type, World worldIn) { super(type, worldIn); } public abstract boolean attackEntityFrom(MultiPartEntityPart entityPart, DamageSource source, float damage); public abstract MultiPartEntityPart[] getAllParts(); } MultiPartEntityPart.class: public class MultiPartEntityPart extends Entity { public final MultiPartEntity parentEntity; public final String partName; private final EntitySize boxSize; public MultiPartEntityPart(MultiPartEntity parentEntity, String partName, float widthIn, float HeightIn) { super(parentEntity.getType(), parentEntity.world); this.boxSize = EntitySize.flexible(widthIn, HeightIn); this.recalculateSize(); this.parentEntity = (MultiPartEntity) parentEntity; this.partName = partName; } protected void registerData() { } protected void readAdditional(CompoundNBT compound) { } protected void writeAdditional(CompoundNBT compound) { } public boolean canBeCollidedWith() { return true; } public boolean attackEntityFrom(DamageSource source, float amount) { return this.parentEntity.attackEntityFrom(this, source, amount); } public boolean isEntityEqual(Entity entityIn) { return this == entityIn || this.parentEntity == entityIn; } public IPacket<?> createSpawnPacket() { throw new UnsupportedOperationException(); } public EntitySize getSize(Pose poseIn) { return this.boxSize; } }
October 18, 20204 yr 22 minutes ago, Narlecks said: public boolean attackEntityFrom(DamageSource source, float amount) { return false; } public boolean attackEntityFrom(MultiPartEntityPart entityPart, DamageSource source, float damage) { System.out.println(entityPart.partName); return true; } Yes, the console output is occurring only whenever you hit the parts. However, it will not cause any damage to the actual entity as that returns false. You need a better descriptor rather than 'it just doesn't work'.
October 18, 20204 yr Author 4 minutes ago, ChampionAsh5357 said: Yes, the console output is occurring only whenever you hit the parts. However, it will not cause any damage to the actual entity as that returns false. You need a better descriptor rather than 'it just doesn't work'. You are right, my bad. When I hit the entity, in the console I don't get any messages
October 18, 20204 yr You should probably put a breakpoint within your part class at attackEntityFrom and see whether it calls the statement as it looks like it should.
October 18, 20204 yr Author It never reaches AttackEntityFrom because the other hitboxes even though they exist, I can't hit them.
October 18, 20204 yr 3 minutes ago, Narlecks said: It never reaches AttackEntityFrom because the other hitboxes even though they exist, I can't hit them. You just ignored what I said. You're telling me an issue based on runtime testing and not on debugging. You can go all the way into Minecraft#clickMouse and put a breakpoint over the case where the RayTraceResult is an ENTITY and view what's getting called where and why. However, telling me the same problem without debugging the process like I mentioned above is just repetition and not solving the issue. So, follow the code from where the entity is clicked on all the way to it's final result. If you are in fact targeting an entity, it should be recognized by the resulting ray trace. You should even be able to verify that your mouse is hovering over the existing entity by simply opening the debug menu.
October 20, 20204 yr Author On 10/18/2020 at 3:54 PM, ChampionAsh5357 said: You just ignored what I said. You're telling me an issue based on runtime testing and not on debugging. You can go all the way into Minecraft#clickMouse and put a breakpoint over the case where the RayTraceResult is an ENTITY and view what's getting called where and why. However, telling me the same problem without debugging the process like I mentioned above is just repetition and not solving the issue. So, follow the code from where the entity is clicked on all the way to it's final result. If you are in fact targeting an entity, it should be recognized by the resulting ray trace. You should even be able to verify that your mouse is hovering over the existing entity by simply opening the debug menu. Thanks for the suggestion!, i solved that problem but i found another.. The problem is, the entity parts have different IDs on client and server So, for example.. when i hit the head, in client-side the hit is received by the head but in server-side is received by the body bc the ids collide Do you have an idea why that can happen? Tell me if u need specific information
October 20, 20204 yr Author one thing I forgot to say is that following the EnderDragon's code i came across this: public void handleSpawnMob(SSpawnMobPacket packetIn) { PacketThreadUtil.checkThreadAndEnqueue(packetIn, (ClientPlayNetHandler) (Object)this, this.client); double d0 = packetIn.getX(); double d1 = packetIn.getY(); double d2 = packetIn.getZ(); float f = (float)(packetIn.getYaw() * 360) / 256.0F; float f1 = (float)(packetIn.getPitch() * 360) / 256.0F; LivingEntity livingentity = (LivingEntity)EntityType.create(packetIn.getEntityType(), this.client.world); if (livingentity != null) { livingentity.setPacketCoordinates(d0, d1, d2); livingentity.renderYawOffset = (float)(packetIn.getHeadPitch() * 360) / 256.0F; livingentity.rotationYawHead = (float)(packetIn.getHeadPitch() * 360) / 256.0F; if (livingentity instanceof EnderDragonEntity) { EnderDragonPartEntity[] aenderdragonpartentity = ((EnderDragonEntity)livingentity).getDragonParts(); for(int i = 0; i < aenderdragonpartentity.length; ++i) { aenderdragonpartentity[i].setEntityId(i + packetIn.getEntityID()); } } if (livingentity instanceof MultiPartEntity) { MultiPartEntityPart[] multipartentitypart = ((MultiPartEntity)livingentity).getAllParts(); for(int i = 0; i < multipartentitypart.length; ++i) { multipartentitypart[i].setEntityId(i + packetIn.getEntityID()); } } livingentity.setEntityId(packetIn.getEntityID()); livingentity.setUniqueId(packetIn.getUniqueId()); livingentity.setPositionAndRotation(d0, d1, d2, f, f1); livingentity.setMotion((double)((float)packetIn.getVelocityX() / 8000.0F), (double)((float)packetIn.getVelocityY() / 8000.0F), (double)((float)packetIn.getVelocityZ() / 8000.0F)); this.world.addEntity(packetIn.getEntityID(), livingentity); if (livingentity instanceof BeeEntity) { boolean flag = ((BeeEntity)livingentity).isAngry(); BeeSound beesound; if (flag) { beesound = new BeeAngrySound((BeeEntity)livingentity); } else { beesound = new BeeFlightSound((BeeEntity)livingentity); } this.client.getSoundHandler().play(beesound); } } else { LOGGER.warn("Skipping Entity with id {}", (int)packetIn.getEntityType()); } } I'm not sure if the error is in this part, but as you can see I added a condition to modify the entityID of each part, I tried it and it works as it should on clientSide
October 20, 20204 yr 4 hours ago, Narlecks said: I'm not sure if the error is in this part, but as you can see I added a condition to modify the entityID of each part, I tried it and it works as it should on clientSide Yes, you got it.
October 20, 20204 yr Author 6 hours ago, ChampionAsh5357 said: Yes, you got it. The problem is, it only works in clientside, the id's on serverside are not the same
October 21, 20204 yr 4 hours ago, Narlecks said: The problem is, it only works in clientside, the id's on serverside are not the same Then sync the serverside ids to the client for each part.
October 21, 20204 yr Author 9 hours ago, ChampionAsh5357 said: Then sync the serverside ids to the client for each part. Any idea where Minecraft does that? or i put it in the same place using packets?
October 21, 20204 yr You should specify the spawning packet as NetworkHooks#getSpawnPacket and use IEntityAdditionalSpawnData to send the ids of each multipart to the client so they may be synchronized.
October 22, 20204 yr Author 22 hours ago, ChampionAsh5357 said: You should specify the spawning packet as NetworkHooks#getSpawnPacket and use IEntityAdditionalSpawnData to send the ids of each multipart to the client so they may be synchronized. in the first instance it worked, but for some reason when hitting it keeps getting different id's on server / client. Did I made a mistake while implementing IEntityAdditionalSpawnData? @Override public IPacket<?> createSpawnPacket() { return NetworkHooks.getEntitySpawningPacket(this); } @Override public void writeSpawnData(PacketBuffer buffer) { int[] id = new int[getAllParts().length]; for(int i=0;i<getAllParts().length;i++) { getAllParts()[i].setEntityId(i+this.getEntityId()); id[i] = i+this.getEntityId(); } buffer.writeVarIntArray(id); } @Override public void readSpawnData(PacketBuffer additionalData) { int[] id = additionalData.readVarIntArray(); for(int i=0;i<getAllParts().length;i++) { getAllParts()[i].setEntityId(id[i]); } }
October 22, 20204 yr You shouldn't need to set the data on the server. Those values are handled via AtomicInteger#incrementAndGet. Therefore, you know that the parts will have the next ids after your entity (e.g. if your main id is 23, then your parts will always be 24 and 25). All you really need to do is just set the entity id itself when you are reading the data with it's specified offset. Nothing needs to be sent to the client. This might be the error you are facing as you could be changing the id when the server already has a set value, but I'm not sure. However, you should try the above and see if it solves your issue.
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.