Jump to content

Recommended Posts

Posted

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;
   }
}

 

Posted
  On 10/18/2020 at 2:26 PM, 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; }

Expand  

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'.

Posted
  On 10/18/2020 at 2:53 PM, 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'.

Expand  

You are right, my bad.

When I hit the entity, in the console I don't get any messages

Posted
  On 10/18/2020 at 6:40 PM, Narlecks said:

It never reaches AttackEntityFrom because the other hitboxes even though they exist, I can't hit them.

Expand  

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.

Posted
  On 10/18/2020 at 6: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.

Expand  

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

Posted

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

 

 

Posted
  On 10/21/2020 at 3:56 PM, 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.

Expand  

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]);
		}
		
	}

 

Posted

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.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hello , when I try to launch the forge installer it just crash with a message for 0,5 secondes. I'm using java 17 to launch it. Here's the link of the error :https://cdn.corenexis.com/view/?img=d/ma24/qs7u4U.jpg  
    • You will find the crash-report or log in your minecraft directory (crash-report or logs folder)
    • Use a modpack which is using these 2 mods as working base:   https://www.curseforge.com/minecraft/modpacks/life-in-the-village-3
    • inicie un mundo donde instale Croptopia y Farmer's Delight, entonces instale el addon Croptopia Delight pero no funciona. es la version 1.18.2
    • Hello all. I'm currently grappling with the updateShape method in a custom class extending Block.  My code currently looks like this: The conditionals in CheckState are there to switch blockstate properties, which is working fine, as it functions correctly every time in getStateForPlacement.  The problem I'm running into is that when I update a state, the blocks seem to call CheckState with the position of the block which was changed updated last.  If I build a wall I can see the same change propagate across. My question thus is this: is updateShape sending its return to the neighbouring block?  Is each block not independently executing the updateShape method, thus inserting its own current position?  The first statement appears to be true, and the second false (each block is not independently executing the method). I have tried to fix this by saving the block's own position to a variable myPos at inception, and then feeding this in as CheckState(myPos) but this causes a worse outcome, where all blocks take the update of the first modified block, rather than just their neighbour.  This raises more questions than it answers, obviously: how is a different instance's variable propagating here?  I also tried changing it so that CheckState did not take a BlockPos, but had myPos built into the body - same problem. I have previously looked at neighbourUpdate and onNeighbourUpdate, but could not find a way to get this to work at all.  One post on here about updatePostPlacement and other methods has proven itself long superceded.  All other sources on the net seem to be out of date. Many thanks in advance for any help you might offer me, it's been several days now of trying to get this work and several weeks of generally trying to get round this roadblock.  - Sandermall
  • Topics

×
×
  • Create New...

Important Information

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