Key.Head_Rotation Bug or Programmer Error?

Sponge Build: spongeforge-1.11.2-2226-6.0.0-BETA-2112
Forge Build: forge-1.11.2-13.20.0.2226-universal
**Java Version:**1.8.0_121-b13

So I tried spawning an entity and I tried to offer it a head rotation, but when the entity spawned, it faced to the default direction. Have I done something wrong here or is this a bug with the Sponge 6.0.0 API?

	Vector3d V3d = new Vector3d(6, 177, 0);
	
	entity.offer(Keys.HEAD_ROTATION, V3d);

Keys.HEAD_ROTATION belongs to ArmorStands. Actually the offer() method should return an error-like thing.
What you want is Entity.setRotation(...).

This only rotates the entity’s body.

In that case you need Living.setHeadRotation.

Note that this only works for entities that are Living (item stacks don’t have a rotatable head, for instance) and that your variable needs to be of type Living or some other type that implements the Living interface.

So based on the error below, I can’t cast my HUMAN to a Player.

java.lang.ClassCastException: org.spongepowered.common.entity.living.human.EntityHuman cannot be cast to org.spongepowered.api.entity.living.player.Player

That’s because a Human isn’t a Player. You cannot cast a variable’s type into something it is not. A Human is a server-controlled creature (AI, NPC, mob) that supposedly looks humanoid, but otherwise hasn’t got a lot in common with a real Player controlled by a Client.

But that leads me to the question what are you really trying to do?

Exactly, this might be a xy problem.

@SalvadorZXA instead of casting the Human to Player, cast it to Living.

1 Like

My ultimate goal is have NPCs that look at the nearest player, but look at a specified direction e.g. WEST if no player is nearby. I obtained this code from Getting Nearest Entity and slightly altered it below.

public Entity getClosestDZNPC(Entity player) {
	
    Entity closest = null;
    
    double closestDistance = 0;

    for (Entity entity : player.getLocation().getExtent().getEntities()) {
    	
        if (entity == player) {
            continue;
        }

        double distance = entity.getLocation().getPosition().distance(player.getLocation().getPosition());
        
        if (closest == null || distance < closestDistance) {
        	
            closest = entity;
            
            closestDistance = distance;
        }
    }
    return closest;
}

I then created a listener that would first find a player’s nearest NPC, then the NPC would find it’s nearest player and stare at them.

@Listener
public void onPlayerNearDZNPC(MoveEntityEvent event, @First Player player){
	
	if(ArenaConfigUtils.getUserArenaNameFromLocation(player.getLocation())!=null){
	
		if(ContestantConfigUtils.isUserAnArenaContestant(ArenaConfigUtils.getUserArenaNameFromLocation(player.getLocation()), player.getName())){
			
			Entity nearestDZNPC = getClosestDZNPC(player);
			
			Living NDZNPC = (Living)nearestDZNPC;
			
		    Entity nearestPlayer = getClosestDZNPC(nearestDZNPC);
		    
		    double x = nearestPlayer.getLocation().getX();
		    
		    double y = nearestPlayer.getLocation().getY();
		    
		    double z = nearestPlayer.getLocation().getZ();
		    
		    Vector3d V3D = new Vector3d(x,y,z);
		    
		    NDZNPC.setHeadRotation(V3D);
		    
		    nearestDZNPC.offer(Keys.SKIN_UNIQUE_ID, nearestPlayer.getUniqueId());
		}
	}
}

As of right now, the NPCs only seem to twitch their heads if a player is nearby.

nearestPlayer can be null if no nearby Entity was found. Executing nearestPlayer.getLocation() should then cause a NPE. Check if the code crashes and add debug messages to check the behavior of your code.

1 Like

Ideally, you should already check in your getClosestNPC() method if the entity you’re iterating over is a Living and if it isn’t continue right before getting the distance (a distance calculation is more expensive than an instanceof), as you’re only interested in entities that are Livings (and right now it seems you don’t check at all whether your Entity is a Living or not, which could blow up in your face when you have one that isn’t a Living and you’re trying to cast it into one in the other method).

Furthermore, that would mean you could return a Living from the first method and you wouldn’t need to cast anymore in your onPlayerNearDZNPC() method.