2022-11-13 16:33:18 +01:00
package net.citizensnpcs.nms.v1_14_R1.entity ;
2019-04-24 15:01:22 +02:00
import java.io.IOException ;
import java.util.List ;
import java.util.Map ;
2023-02-22 17:06:13 +01:00
2019-04-24 15:01:22 +02:00
import org.bukkit.Bukkit ;
2022-12-28 16:14:41 +01:00
import org.bukkit.GameMode ;
2019-04-24 15:01:22 +02:00
import org.bukkit.Location ;
import org.bukkit.craftbukkit.v1_14_R1.CraftServer ;
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer ;
import org.bukkit.entity.Player ;
import org.bukkit.metadata.MetadataValue ;
import org.bukkit.plugin.Plugin ;
import org.bukkit.util.Vector ;
2023-02-22 17:06:13 +01:00
2019-04-24 15:01:22 +02:00
import com.google.common.collect.Maps ;
import com.mojang.authlib.GameProfile ;
2023-02-22 17:06:13 +01:00
2019-04-24 15:01:22 +02:00
import net.citizensnpcs.Settings.Setting ;
import net.citizensnpcs.api.CitizensAPI ;
import net.citizensnpcs.api.npc.NPC ;
2023-01-01 08:26:35 +01:00
import net.citizensnpcs.api.npc.NPC.NPCUpdate ;
2019-04-24 15:01:22 +02:00
import net.citizensnpcs.api.trait.trait.Inventory ;
2022-07-07 17:34:15 +02:00
import net.citizensnpcs.api.util.SpigotUtil ;
2019-04-24 15:01:22 +02:00
import net.citizensnpcs.nms.v1_14_R1.network.EmptyNetHandler ;
import net.citizensnpcs.nms.v1_14_R1.network.EmptyNetworkManager ;
import net.citizensnpcs.nms.v1_14_R1.util.EmptyAdvancementDataPlayer ;
import net.citizensnpcs.nms.v1_14_R1.util.NMSImpl ;
import net.citizensnpcs.nms.v1_14_R1.util.PlayerControllerJump ;
import net.citizensnpcs.nms.v1_14_R1.util.PlayerControllerMove ;
import net.citizensnpcs.nms.v1_14_R1.util.PlayerNavigation ;
2020-05-16 13:13:19 +02:00
import net.citizensnpcs.nms.v1_14_R1.util.PlayerlistTracker ;
2019-04-24 15:01:22 +02:00
import net.citizensnpcs.npc.CitizensNPC ;
import net.citizensnpcs.npc.ai.NPCHolder ;
import net.citizensnpcs.npc.skin.SkinPacketTracker ;
import net.citizensnpcs.npc.skin.SkinnableEntity ;
import net.citizensnpcs.trait.Gravity ;
2020-04-18 20:07:03 +02:00
import net.citizensnpcs.trait.SkinTrait ;
2019-04-24 15:01:22 +02:00
import net.citizensnpcs.util.NMS ;
import net.citizensnpcs.util.Util ;
import net.minecraft.server.v1_14_R1.AttributeInstance ;
2022-11-10 14:31:32 +01:00
import net.minecraft.server.v1_14_R1.AxisAlignedBB ;
2019-04-24 15:01:22 +02:00
import net.minecraft.server.v1_14_R1.BlockPosition ;
import net.minecraft.server.v1_14_R1.ChatComponentText ;
import net.minecraft.server.v1_14_R1.DamageSource ;
2022-11-10 14:31:32 +01:00
import net.minecraft.server.v1_14_R1.Entity ;
2019-04-24 15:01:22 +02:00
import net.minecraft.server.v1_14_R1.EntityHuman ;
import net.minecraft.server.v1_14_R1.EntityPlayer ;
import net.minecraft.server.v1_14_R1.EnumGamemode ;
import net.minecraft.server.v1_14_R1.EnumItemSlot ;
import net.minecraft.server.v1_14_R1.EnumProtocolDirection ;
import net.minecraft.server.v1_14_R1.GenericAttributes ;
import net.minecraft.server.v1_14_R1.IBlockData ;
import net.minecraft.server.v1_14_R1.IChatBaseComponent ;
2021-01-24 12:25:59 +01:00
import net.minecraft.server.v1_14_R1.ItemStack ;
2019-04-24 15:01:22 +02:00
import net.minecraft.server.v1_14_R1.MinecraftServer ;
import net.minecraft.server.v1_14_R1.NavigationAbstract ;
import net.minecraft.server.v1_14_R1.NetworkManager ;
import net.minecraft.server.v1_14_R1.Packet ;
import net.minecraft.server.v1_14_R1.PacketPlayOutEntityEquipment ;
import net.minecraft.server.v1_14_R1.PathType ;
import net.minecraft.server.v1_14_R1.PlayerInteractManager ;
2022-06-24 06:43:23 +02:00
import net.minecraft.server.v1_14_R1.SoundEffect ;
2019-04-24 15:01:22 +02:00
import net.minecraft.server.v1_14_R1.Vec3D ;
import net.minecraft.server.v1_14_R1.WorldServer ;
public class EntityHumanNPC extends EntityPlayer implements NPCHolder , SkinnableEntity {
private final Map < PathType , Float > bz = Maps . newEnumMap ( PathType . class ) ;
private PlayerControllerJump controllerJump ;
private PlayerControllerMove controllerMove ;
2021-01-24 12:25:59 +01:00
private final Map < EnumItemSlot , ItemStack > equipmentCache = Maps . newEnumMap ( EnumItemSlot . class ) ;
2019-04-24 15:01:22 +02:00
private int jumpTicks = 0 ;
private PlayerNavigation navigation ;
private final CitizensNPC npc ;
private final Location packetLocationCache = new Location ( null , 0 , 0 , 0 ) ;
2020-05-16 13:13:19 +02:00
private PlayerlistTracker playerlistTracker ;
2019-04-24 15:01:22 +02:00
private final SkinPacketTracker skinTracker ;
public EntityHumanNPC ( MinecraftServer minecraftServer , WorldServer world , GameProfile gameProfile ,
PlayerInteractManager playerInteractManager , NPC npc ) {
super ( minecraftServer , world , gameProfile , playerInteractManager ) ;
2023-10-01 11:27:38 +02:00
this . getAttributeInstance ( GenericAttributes . MOVEMENT_SPEED ) . setValue ( 0 . 3D ) ;
2019-04-24 15:01:22 +02:00
this . npc = ( CitizensNPC ) npc ;
if ( npc ! = null ) {
skinTracker = new SkinPacketTracker ( this ) ;
playerInteractManager . setGameMode ( EnumGamemode . SURVIVAL ) ;
initialise ( minecraftServer ) ;
} else {
skinTracker = null ;
}
}
@Override
protected void a ( double d0 , boolean flag , IBlockData block , BlockPosition blockposition ) {
if ( npc = = null | | ! npc . isFlyable ( ) ) {
super . a ( d0 , flag , block , blockposition ) ;
}
}
@Override
public boolean a ( EntityPlayer entityplayer ) {
2023-11-05 09:35:22 +01:00
if ( npc ! = null & & playerlistTracker = = null )
2019-04-24 15:01:22 +02:00
return false ;
return super . a ( entityplayer ) ;
}
public float a ( PathType pathtype ) {
2022-11-13 16:33:18 +01:00
return this . bz . containsKey ( pathtype ) ? this . bz . get ( pathtype ) : pathtype . a ( ) ;
2019-04-24 15:01:22 +02:00
}
public void a ( PathType pathtype , float f ) {
2022-11-13 16:33:18 +01:00
this . bz . put ( pathtype , f ) ;
2019-04-24 15:01:22 +02:00
}
@Override
public void b ( float f , float f1 ) {
if ( npc = = null | | ! npc . isFlyable ( ) ) {
super . b ( f , f1 ) ;
}
}
@Override
public void collide ( net . minecraft . server . v1_14_R1 . Entity entity ) {
// this method is called by both the entities involved - cancelling
// it will not stop the NPC from moving.
super . collide ( entity ) ;
if ( npc ! = null ) {
Util . callCollisionEvent ( npc , entity . getBukkitEntity ( ) ) ;
}
}
@Override
public boolean damageEntity ( DamageSource damagesource , float f ) {
// knock back velocity is cancelled and sent to client for handling when
// the entity is a player. there is no client so make this happen
// manually.
boolean damaged = super . damageEntity ( damagesource , f ) ;
if ( damaged & & velocityChanged ) {
velocityChanged = false ;
2023-11-05 09:35:22 +01:00
Bukkit . getScheduler ( ) . runTask ( CitizensAPI . getPlugin ( ) , ( Runnable ) ( ) - > EntityHumanNPC . this . velocityChanged = true ) ;
2019-04-24 15:01:22 +02:00
}
return damaged ;
}
@Override
public void die ( ) {
super . die ( ) ;
getAdvancementData ( ) . a ( ) ;
}
@Override
public void die ( DamageSource damagesource ) {
// players that die are not normally removed from the world. when the
// NPC dies, we are done with the instance and it should be removed.
2023-11-05 09:35:22 +01:00
if ( dead )
2019-04-24 15:01:22 +02:00
return ;
super . die ( damagesource ) ;
2023-11-05 09:35:22 +01:00
Bukkit . getScheduler ( ) . runTaskLater ( CitizensAPI . getPlugin ( ) , ( Runnable ) ( ) - > ( ( WorldServer ) world ) . removeEntity ( EntityHumanNPC . this ) , 15 ) ; // give enough time for death and smoke animation
2019-04-24 15:01:22 +02:00
}
@Override
public void e ( Vec3D vec3d ) {
if ( npc = = null | | ! npc . isFlyable ( ) ) {
super . e ( vec3d ) ;
} else {
NMSImpl . flyingMoveLogic ( this , vec3d ) ;
}
}
@Override
public void f ( double x , double y , double z ) {
2021-01-02 17:09:21 +01:00
Vector vector = Util . callPushEvent ( npc , x , y , z ) ;
if ( vector ! = null ) {
2019-04-24 15:01:22 +02:00
super . f ( vector . getX ( ) , vector . getY ( ) , vector . getZ ( ) ) ;
}
}
@Override
public CraftPlayer getBukkitEntity ( ) {
2019-06-02 17:36:47 +02:00
if ( npc ! = null & & ! ( super . getBukkitEntity ( ) instanceof NPCHolder ) ) {
NMSImpl . setBukkitEntity ( this , new PlayerNPC ( this ) ) ;
2019-04-24 15:01:22 +02:00
}
return super . getBukkitEntity ( ) ;
}
public PlayerControllerJump getControllerJump ( ) {
return controllerJump ;
}
public PlayerControllerMove getControllerMove ( ) {
return controllerMove ;
}
public NavigationAbstract getNavigation ( ) {
return navigation ;
}
@Override
public NPC getNPC ( ) {
return npc ;
}
@Override
public IChatBaseComponent getPlayerListName ( ) {
2023-11-05 09:35:22 +01:00
if ( Setting . DISABLE_TABLIST . asBoolean ( ) )
2019-04-24 15:01:22 +02:00
return new ChatComponentText ( " " ) ;
return super . getPlayerListName ( ) ;
}
@Override
public String getSkinName ( ) {
2020-09-14 11:57:58 +02:00
String skinName = npc . getOrAddTrait ( SkinTrait . class ) . getSkinName ( ) ;
2019-04-24 15:01:22 +02:00
if ( skinName = = null ) {
2020-08-11 16:47:45 +02:00
skinName = npc . getName ( ) ;
2019-04-24 15:01:22 +02:00
}
return skinName . toLowerCase ( ) ;
}
@Override
public SkinPacketTracker getSkinTracker ( ) {
return skinTracker ;
}
2022-06-24 06:43:23 +02:00
@Override
protected SoundEffect getSoundDeath ( ) {
2023-01-01 08:26:35 +01:00
return NMSImpl . getSoundEffect ( npc , super . getSoundDeath ( ) , NPC . Metadata . DEATH_SOUND ) ;
2022-06-24 06:43:23 +02:00
}
@Override
protected SoundEffect getSoundHurt ( DamageSource damagesource ) {
2023-01-01 08:26:35 +01:00
return NMSImpl . getSoundEffect ( npc , super . getSoundHurt ( damagesource ) , NPC . Metadata . HURT_SOUND ) ;
2022-06-24 06:43:23 +02:00
}
2020-11-14 10:27:54 +01:00
@Override
public boolean inBlock ( ) {
2023-11-05 09:35:22 +01:00
if ( npc = = null | | noclip | | isSleeping ( ) )
2020-11-14 10:27:54 +01:00
return super . inBlock ( ) ;
2020-11-14 11:41:21 +01:00
return Util . inBlock ( getBukkitEntity ( ) ) ;
2020-11-14 10:27:54 +01:00
}
2019-04-24 15:01:22 +02:00
private void initialise ( MinecraftServer minecraftServer ) {
try {
2023-10-01 11:27:38 +02:00
NetworkManager conn = new EmptyNetworkManager ( EnumProtocolDirection . CLIENTBOUND ) ;
2019-04-24 15:01:22 +02:00
playerConnection = new EmptyNetHandler ( minecraftServer , conn , this ) ;
conn . setPacketListener ( playerConnection ) ;
} catch ( IOException e ) {
}
AttributeInstance range = getAttributeInstance ( GenericAttributes . FOLLOW_RANGE ) ;
if ( range = = null ) {
range = getAttributeMap ( ) . b ( GenericAttributes . FOLLOW_RANGE ) ;
}
range . setValue ( Setting . DEFAULT_PATHFINDING_RANGE . asDouble ( ) ) ;
controllerJump = new PlayerControllerJump ( this ) ;
controllerMove = new PlayerControllerMove ( this ) ;
navigation = new PlayerNavigation ( this , world ) ;
2020-09-01 17:51:17 +02:00
invulnerableTicks = 0 ;
2019-04-24 15:01:22 +02:00
NMS . setStepHeight ( getBukkitEntity ( ) , 1 ) ; // the default (0) breaks step climbing
setSkinFlags ( ( byte ) 0xFF ) ;
EmptyAdvancementDataPlayer . clear ( this . getAdvancementData ( ) ) ;
NMSImpl . setAdvancement ( this . getBukkitEntity ( ) ,
new EmptyAdvancementDataPlayer ( minecraftServer , CitizensAPI . getDataFolder ( ) . getParentFile ( ) , this ) ) ;
}
@Override
public boolean isClimbing ( ) {
2023-11-05 09:35:22 +01:00
if ( npc = = null | | ! npc . isFlyable ( ) )
2019-04-24 15:01:22 +02:00
return super . isClimbing ( ) ;
2023-11-05 09:35:22 +01:00
else
2019-04-24 15:01:22 +02:00
return false ;
}
@Override
public boolean isCollidable ( ) {
2022-01-20 10:10:52 +01:00
return npc = = null ? super . isCollidable ( )
2023-01-01 08:26:35 +01:00
: npc . data ( ) . has ( NPC . Metadata . COLLIDABLE ) ? npc . data ( ) . < Boolean > get ( NPC . Metadata . COLLIDABLE )
2022-01-20 10:10:52 +01:00
: ! npc . isProtected ( ) ;
2019-04-24 15:01:22 +02:00
}
public boolean isNavigating ( ) {
return npc . getNavigator ( ) . isNavigating ( ) ;
}
private void moveOnCurrentHeading ( ) {
if ( jumping ) {
if ( onGround & & jumpTicks = = 0 ) {
jump ( ) ;
jumpTicks = 10 ;
}
} else {
jumpTicks = 0 ;
}
bb * = 0 . 98F ;
bd * = 0 . 98F ;
be * = 0 . 9F ;
2021-10-24 18:22:19 +02:00
moveWithFallDamage ( new Vec3D ( this . bb , this . bc , this . bd ) ) ; // movement method
2019-04-24 15:01:22 +02:00
NMS . setHeadYaw ( getBukkitEntity ( ) , yaw ) ;
if ( jumpTicks > 0 ) {
jumpTicks - - ;
}
}
2021-10-24 18:22:19 +02:00
private void moveWithFallDamage ( Vec3D vec ) {
double y = this . locY ;
e ( vec ) ;
if ( ! npc . isProtected ( ) ) {
a ( this . locY - y , onGround ) ;
}
}
2020-04-29 14:56:39 +02:00
@Override
public void playerTick ( ) {
if ( npc = = null ) {
super . playerTick ( ) ;
return ;
}
entityBaseTick ( ) ;
2022-11-07 16:30:39 +01:00
boolean navigating = npc . getNavigator ( ) . isNavigating ( ) | | controllerMove . b ( ) ;
2020-07-27 11:14:57 +02:00
if ( ! navigating & & getBukkitEntity ( ) ! = null
2020-09-14 11:57:58 +02:00
& & ( ! npc . hasTrait ( Gravity . class ) | | npc . getOrAddTrait ( Gravity . class ) . hasGravity ( ) )
2022-07-07 17:34:15 +02:00
& & Util . isLoaded ( getBukkitEntity ( ) . getLocation ( LOADED_LOCATION ) )
2023-10-01 11:27:38 +02:00
& & ( ! npc . isProtected ( ) | | SpigotUtil . checkYSafe ( locY , getBukkitEntity ( ) . getWorld ( ) ) ) ) {
2021-10-24 18:22:19 +02:00
moveWithFallDamage ( new Vec3D ( 0 , 0 , 0 ) ) ;
2020-07-27 11:14:57 +02:00
}
Vec3D mot = getMot ( ) ;
if ( Math . abs ( mot . getX ( ) ) < EPSILON & & Math . abs ( mot . getY ( ) ) < EPSILON & & Math . abs ( mot . getZ ( ) ) < EPSILON ) {
setMot ( new Vec3D ( 0 , 0 , 0 ) ) ;
}
if ( navigating ) {
if ( ! NMSImpl . isNavigationFinished ( navigation ) ) {
NMSImpl . updateNavigation ( navigation ) ;
}
moveOnCurrentHeading ( ) ;
}
2023-01-05 15:51:42 +01:00
updateAI ( ) ;
2023-05-03 19:20:57 +02:00
collideNearby ( ) ;
2023-02-26 08:51:59 +01:00
if ( npc . data ( ) . get ( NPC . Metadata . PICKUP_ITEMS , false ) ) {
2022-11-10 14:31:32 +01:00
AxisAlignedBB axisalignedbb ;
if ( this . isPassenger ( ) & & ! this . getVehicle ( ) . dead ) {
axisalignedbb = this . getBoundingBox ( ) . b ( this . getVehicle ( ) . getBoundingBox ( ) ) . grow ( 1 . 0 , 0 . 0 , 1 . 0 ) ;
} else {
axisalignedbb = this . getBoundingBox ( ) . grow ( 1 . 0 , 0 . 5 , 1 . 0 ) ;
}
for ( Entity entity : this . world . getEntities ( this , axisalignedbb ) ) {
if ( ! entity . dead ) {
entity . pickup ( this ) ;
}
}
}
2020-04-29 14:56:39 +02:00
}
2019-04-24 15:01:22 +02:00
public void setMoveDestination ( double x , double y , double z , double speed ) {
controllerMove . a ( x , y , z , speed ) ;
}
public void setShouldJump ( ) {
controllerJump . jump ( ) ;
}
@Override
public void setSkinFlags ( byte flags ) {
// set skin flag byte
getDataWatcher ( ) . set ( EntityHuman . bt , flags ) ;
}
@Override
public void setSkinName ( String name ) {
2020-09-14 11:57:58 +02:00
npc . getOrAddTrait ( SkinTrait . class ) . setSkinName ( name ) ;
2019-04-24 15:01:22 +02:00
}
@Override
public void setSkinName ( String name , boolean forceUpdate ) {
2020-09-14 11:57:58 +02:00
npc . getOrAddTrait ( SkinTrait . class ) . setSkinName ( name , forceUpdate ) ;
2019-04-24 15:01:22 +02:00
}
@Override
public void setSkinPersistent ( String skinName , String signature , String data ) {
2020-09-14 11:57:58 +02:00
npc . getOrAddTrait ( SkinTrait . class ) . setSkinPersistent ( skinName , signature , data ) ;
2019-04-24 15:01:22 +02:00
}
2020-05-16 13:13:19 +02:00
public void setTracked ( PlayerlistTracker tracker ) {
this . playerlistTracker = tracker ;
2019-04-24 15:01:22 +02:00
}
@Override
public void tick ( ) {
super . tick ( ) ;
if ( npc = = null )
return ;
this . noclip = isSpectator ( ) ;
2019-06-02 17:36:47 +02:00
Bukkit . getServer ( ) . getPluginManager ( ) . unsubscribeFromPermission ( " bukkit.broadcast.user " , getBukkitEntity ( ) ) ;
2019-04-24 15:01:22 +02:00
boolean navigating = npc . getNavigator ( ) . isNavigating ( ) ;
updatePackets ( navigating ) ;
npc . update ( ) ;
}
public void updateAI ( ) {
controllerMove . a ( ) ;
controllerJump . b ( ) ;
}
private void updatePackets ( boolean navigating ) {
2023-01-01 08:26:35 +01:00
if ( ! npc . isUpdating ( NPCUpdate . PACKET ) )
2022-04-23 07:42:48 +02:00
return ;
2023-03-30 17:13:38 +02:00
2023-01-01 08:26:35 +01:00
updateEffects = true ;
2021-01-24 12:25:59 +01:00
boolean itemChanged = false ;
for ( EnumItemSlot slot : EnumItemSlot . values ( ) ) {
ItemStack equipment = getEquipment ( slot ) ;
2021-01-24 13:51:12 +01:00
ItemStack cache = equipmentCache . get ( slot ) ;
2023-11-05 09:35:22 +01:00
if ( ( ( cache ! = null ) | | ( equipment ! = null ) )
2021-01-24 13:51:12 +01:00
& & ( cache = = null ^ equipment = = null | | ! ItemStack . equals ( cache , equipment ) ) ) {
2021-01-24 12:25:59 +01:00
itemChanged = true ;
2023-04-11 12:16:56 +02:00
if ( cache ! = null & & ! cache . isEmpty ( ) ) {
2023-04-10 18:10:45 +02:00
this . getAttributeMap ( ) . a ( cache . a ( slot ) ) ;
}
2023-04-11 12:16:56 +02:00
if ( equipment ! = null & & ! equipment . isEmpty ( ) ) {
2023-04-10 18:10:45 +02:00
this . getAttributeMap ( ) . b ( equipment . a ( slot ) ) ;
}
2021-01-24 12:25:59 +01:00
}
equipmentCache . put ( slot , equipment ) ;
}
2022-04-23 07:42:48 +02:00
if ( ! itemChanged )
2019-04-24 15:01:22 +02:00
return ;
Location current = getBukkitEntity ( ) . getLocation ( packetLocationCache ) ;
2020-05-01 11:49:03 +02:00
Packet < ? > [ ] packets = new Packet [ EnumItemSlot . values ( ) . length ] ;
2019-04-24 15:01:22 +02:00
int i = 0 ;
for ( EnumItemSlot slot : EnumItemSlot . values ( ) ) {
packets [ i + + ] = new PacketPlayOutEntityEquipment ( getId ( ) , slot , getEquipment ( slot ) ) ;
}
NMSImpl . sendPacketsNearby ( getBukkitEntity ( ) , current , packets ) ;
}
public void updatePathfindingRange ( float pathfindingRange ) {
this . navigation . setRange ( pathfindingRange ) ;
}
public static class PlayerNPC extends CraftPlayer implements NPCHolder , SkinnableEntity {
private final CraftServer cserver ;
private final CitizensNPC npc ;
private PlayerNPC ( EntityHumanNPC entity ) {
super ( ( CraftServer ) Bukkit . getServer ( ) , entity ) ;
this . npc = entity . npc ;
this . cserver = ( CraftServer ) Bukkit . getServer ( ) ;
2020-09-14 11:57:58 +02:00
npc . getOrAddTrait ( Inventory . class ) ;
2019-04-24 15:01:22 +02:00
}
@Override
public Player getBukkitEntity ( ) {
return this ;
}
@Override
public EntityHumanNPC getHandle ( ) {
return ( EntityHumanNPC ) this . entity ;
}
@Override
public List < MetadataValue > getMetadata ( String metadataKey ) {
return cserver . getEntityMetadata ( ) . getMetadata ( this , metadataKey ) ;
}
@Override
public NPC getNPC ( ) {
return npc ;
}
@Override
public String getSkinName ( ) {
return ( ( SkinnableEntity ) this . entity ) . getSkinName ( ) ;
}
@Override
public SkinPacketTracker getSkinTracker ( ) {
return ( ( SkinnableEntity ) this . entity ) . getSkinTracker ( ) ;
}
@Override
public boolean hasMetadata ( String metadataKey ) {
return cserver . getEntityMetadata ( ) . hasMetadata ( this , metadataKey ) ;
}
@Override
public void removeMetadata ( String metadataKey , Plugin owningPlugin ) {
cserver . getEntityMetadata ( ) . removeMetadata ( this , metadataKey , owningPlugin ) ;
2022-12-28 16:14:41 +01:00
}
@Override
public void setGameMode ( GameMode mode ) {
super . setGameMode ( mode ) ;
getHandle ( ) . noclip = mode = = GameMode . SPECTATOR ;
2019-04-24 15:01:22 +02:00
}
@Override
public void setMetadata ( String metadataKey , MetadataValue newMetadataValue ) {
cserver . getEntityMetadata ( ) . setMetadata ( this , metadataKey , newMetadataValue ) ;
}
@Override
public void setSkinFlags ( byte flags ) {
( ( SkinnableEntity ) this . entity ) . setSkinFlags ( flags ) ;
}
@Override
public void setSkinName ( String name ) {
( ( SkinnableEntity ) this . entity ) . setSkinName ( name ) ;
}
@Override
public void setSkinName ( String skinName , boolean forceUpdate ) {
( ( SkinnableEntity ) this . entity ) . setSkinName ( skinName , forceUpdate ) ;
}
@Override
public void setSkinPersistent ( String skinName , String signature , String data ) {
( ( SkinnableEntity ) this . entity ) . setSkinPersistent ( skinName , signature , data ) ;
}
}
private static final float EPSILON = 0 . 005F ;
private static final Location LOADED_LOCATION = new Location ( null , 0 , 0 , 0 ) ;
}