package org.bukkit.craftbukkit.entity ;
import com.google.common.collect.ImmutableSet ;
import com.google.common.collect.MapMaker ;
import java.io.ByteArrayOutputStream ;
import java.io.IOException ;
import java.net.InetSocketAddress ;
import java.net.SocketAddress ;
import java.util.Collection ;
import java.util.HashSet ;
import java.util.LinkedHashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
import java.util.UUID ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
import com.mojang.authlib.GameProfile ;
import net.minecraft.entity.EntityTracker ;
import net.minecraft.entity.EntityTrackerEntry ;
import net.minecraft.entity.player.EntityPlayerMP ;
import net.minecraft.network.play.server.S23PacketBlockChange ;
import net.minecraft.network.play.server.S33PacketUpdateSign ;
import net.minecraft.network.play.server.S38PacketPlayerListItem ;
import net.minecraft.world.WorldServer ;
import org.apache.commons.lang.Validate ;
import org.apache.commons.lang.NotImplementedException ;
import org.bukkit.* ;
import org.bukkit.Statistic.Type ;
import org.bukkit.configuration.serialization.DelegateDeserialization ;
import org.bukkit.conversations.Conversation ;
import org.bukkit.conversations.ConversationAbandonedEvent ;
import org.bukkit.conversations.ManuallyAbandonedConversationCanceller ;
import org.bukkit.craftbukkit.block.CraftSign ;
import org.bukkit.craftbukkit.conversations.ConversationTracker ;
import org.bukkit.craftbukkit.CraftEffect ;
import org.bukkit.craftbukkit.CraftOfflinePlayer ;
import org.bukkit.craftbukkit.CraftServer ;
import org.bukkit.craftbukkit.CraftSound ;
import org.bukkit.craftbukkit.CraftStatistic ;
import org.bukkit.craftbukkit.CraftWorld ;
import org.bukkit.craftbukkit.map.CraftMapView ;
import org.bukkit.craftbukkit.map.RenderData ;
import org.bukkit.craftbukkit.scoreboard.CraftScoreboard ;
import org.bukkit.craftbukkit.util.CraftChatMessage ;
import org.bukkit.craftbukkit.util.CraftMagicNumbers ;
import org.bukkit.entity.EntityType ;
import org.bukkit.entity.Player ;
import org.bukkit.event.player.PlayerGameModeChangeEvent ;
import org.bukkit.event.player.PlayerRegisterChannelEvent ;
import org.bukkit.event.player.PlayerTeleportEvent ;
import org.bukkit.event.player.PlayerUnregisterChannelEvent ;
import org.bukkit.inventory.InventoryView.Property ;
import org.bukkit.map.MapView ;
import org.bukkit.metadata.MetadataValue ;
import org.bukkit.plugin.Plugin ;
import org.bukkit.plugin.messaging.StandardMessenger ;
import org.bukkit.scoreboard.Scoreboard ;
@DelegateDeserialization ( CraftOfflinePlayer . class )
public class CraftPlayer extends CraftHumanEntity implements Player {
private long firstPlayed = 0 ;
private long lastPlayed = 0 ;
private boolean hasPlayedBefore = false ;
private final ConversationTracker conversationTracker = new ConversationTracker ( ) ;
private final Set < String > channels = new HashSet < String > ( ) ;
private final Set < UUID > hiddenPlayers = new HashSet < UUID > ( ) ;
private int hash = 0 ;
private double health = 20 ;
private boolean scaledHealth = false ;
private double healthScale = 20 ;
public CraftPlayer ( CraftServer server , net . minecraft . entity . player . EntityPlayerMP entity ) {
super ( server , entity ) ;
firstPlayed = System . currentTimeMillis ( ) ;
}
public GameProfile getProfile ( ) {
return getHandle ( ) . getGameProfile ( ) ;
}
@Override
public boolean isOp ( ) {
return server . getHandle ( ) . func_152596_g ( getProfile ( ) ) ;
}
@Override
public void setOp ( boolean value ) {
if ( value = = isOp ( ) ) return ;
if ( value ) {
server . getHandle ( ) . func_152605_a ( getProfile ( ) ) ;
} else {
server . getHandle ( ) . func_152610_b ( getProfile ( ) ) ;
}
perm . recalculatePermissions ( ) ;
}
public boolean isOnline ( ) {
for ( Object obj : server . getHandle ( ) . playerEntityList ) {
net . minecraft . entity . player . EntityPlayerMP player = ( net . minecraft . entity . player . EntityPlayerMP ) obj ;
if ( player . getCommandSenderName ( ) . equalsIgnoreCase ( getName ( ) ) ) {
return true ;
}
}
return false ;
}
public InetSocketAddress getAddress ( ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return null ;
SocketAddress addr = getHandle ( ) . playerNetServerHandler . netManager . getSocketAddress ( ) ;
if ( addr instanceof InetSocketAddress ) {
return ( InetSocketAddress ) addr ;
} else {
return null ;
}
}
@Override
public double getEyeHeight ( ) {
return getEyeHeight ( false ) ;
}
@Override
public double getEyeHeight ( boolean ignoreSneaking ) {
if ( ignoreSneaking ) {
return 1 . 62D ;
} else {
if ( isSneaking ( ) ) {
return 1 . 54D ;
} else {
return 1 . 62D ;
}
}
}
@Override
public void sendRawMessage ( String message ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
for ( net . minecraft . util . IChatComponent component : CraftChatMessage . fromString ( message ) ) {
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S02PacketChat ( component ) ) ;
}
}
@Override
public void sendMessage ( String message ) {
if ( ! conversationTracker . isConversingModaly ( ) ) {
this . sendRawMessage ( message ) ;
}
}
@Override
public void sendMessage ( String [ ] messages ) {
for ( String message : messages ) {
sendMessage ( message ) ;
}
}
@Override
public String getDisplayName ( ) {
return getHandle ( ) . displayName ;
}
@Override
public void setDisplayName ( final String name ) {
getHandle ( ) . displayName = name = = null ? getName ( ) : name ;
}
@Override
public String getPlayerListName ( ) {
return getHandle ( ) . listName ;
}
@Override
public void setPlayerListName ( String name ) {
String oldName = getHandle ( ) . listName ;
if ( name = = null ) {
name = getName ( ) ;
}
if ( oldName . equals ( name ) ) {
return ;
}
if ( name . length ( ) > 16 ) {
throw new IllegalArgumentException ( "Player list names can only be a maximum of 16 characters long" ) ;
}
// Collisions will make for invisible people
for ( int i = 0 ; i < server . getHandle ( ) . playerEntityList . size ( ) ; + + i ) {
if ( ( ( net . minecraft . entity . player . EntityPlayerMP ) server . getHandle ( ) . playerEntityList . get ( i ) ) . listName . equals ( name ) ) {
throw new IllegalArgumentException ( name + " is already assigned as a player list name for someone" ) ;
}
}
getHandle ( ) . listName = name ;
// Change the name on the client side
net . minecraft . network . play . server . S38PacketPlayerListItem oldpacket = new net . minecraft . network . play . server . S38PacketPlayerListItem ( oldName , false , 9999 ) ;
net . minecraft . network . play . server . S38PacketPlayerListItem packet = new net . minecraft . network . play . server . S38PacketPlayerListItem ( name , true , getHandle ( ) . ping ) ;
for ( int i = 0 ; i < server . getHandle ( ) . playerEntityList . size ( ) ; + + i ) {
net . minecraft . entity . player . EntityPlayerMP entityplayer = ( net . minecraft . entity . player . EntityPlayerMP ) server . getHandle ( ) . playerEntityList . get ( i ) ;
if ( entityplayer . playerNetServerHandler = = null ) continue ;
if ( entityplayer . getBukkitEntity ( ) . canSee ( this ) ) {
entityplayer . playerNetServerHandler . sendPacket ( oldpacket ) ;
entityplayer . playerNetServerHandler . sendPacket ( packet ) ;
}
}
}
@Override
public boolean equals ( Object obj ) {
if ( ! ( obj instanceof OfflinePlayer ) ) {
return false ;
}
OfflinePlayer other = ( OfflinePlayer ) obj ;
if ( ( this . getName ( ) = = null ) | | ( other . getName ( ) = = null ) ) {
return false ;
}
boolean nameEquals = this . getName ( ) . equalsIgnoreCase ( other . getName ( ) ) ;
boolean idEquals = true ;
if ( other instanceof CraftPlayer ) {
idEquals = this . getEntityId ( ) = = ( ( CraftPlayer ) other ) . getEntityId ( ) ;
}
return nameEquals & & idEquals ;
}
@Override
public void kickPlayer ( String message ) {
if ( Thread . currentThread ( ) ! = net . minecraft . server . MinecraftServer . getServer ( ) . primaryThread ) throw new IllegalStateException ( "Asynchronous player kick!" ) ; // Spigot
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
getHandle ( ) . playerNetServerHandler . kickPlayerFromServer ( message = = null ? "" : message ) ;
}
@Override
public void setCompassTarget ( Location loc ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
// Do not directly assign here, from the packethandler we'll assign it.
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S05PacketSpawnPosition ( loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) ) ) ;
}
@Override
public Location getCompassTarget ( ) {
return getHandle ( ) . compassTarget ;
}
@Override
public void chat ( String msg ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
getHandle ( ) . playerNetServerHandler . chat ( msg , false ) ;
}
@Override
public boolean performCommand ( String command ) {
return server . dispatchCommand ( this , command ) ;
}
@Override
public void playNote ( Location loc , byte instrument , byte note ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
String instrumentName = null ;
switch ( instrument ) {
case 0 :
instrumentName = "harp" ;
break ;
case 1 :
instrumentName = "bd" ;
break ;
case 2 :
instrumentName = "snare" ;
break ;
case 3 :
instrumentName = "hat" ;
break ;
case 4 :
instrumentName = "bassattack" ;
break ;
}
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S29PacketSoundEffect ( "note." + instrumentName , loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) , 3 . 0f , note ) ) ;
}
@Override
public void playNote ( Location loc , Instrument instrument , Note note ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
String instrumentName = null ;
switch ( instrument . ordinal ( ) ) {
case 0 :
instrumentName = "harp" ;
break ;
case 1 :
instrumentName = "bd" ;
break ;
case 2 :
instrumentName = "snare" ;
break ;
case 3 :
instrumentName = "hat" ;
break ;
case 4 :
instrumentName = "bassattack" ;
break ;
}
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S29PacketSoundEffect ( "note." + instrumentName , loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) , 3 . 0f , note . getId ( ) ) ) ;
}
@Override
public void playSound ( Location loc , Sound sound , float volume , float pitch ) {
if ( sound = = null ) {
return ;
}
playSound ( loc , CraftSound . getSound ( sound ) , volume , pitch ) ;
}
@Override
public void playSound ( Location loc , String sound , float volume , float pitch ) {
if ( loc = = null | | sound = = null | | getHandle ( ) . playerNetServerHandler = = null ) return ;
double x = loc . getBlockX ( ) + 0 . 5 ;
double y = loc . getBlockY ( ) + 0 . 5 ;
double z = loc . getBlockZ ( ) + 0 . 5 ;
net . minecraft . network . play . server . S29PacketSoundEffect packet = new net . minecraft . network . play . server . S29PacketSoundEffect ( sound , x , y , z , volume , pitch ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( packet ) ;
}
@Override
public void playEffect ( Location loc , Effect effect , int data ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
int packetData = effect . getId ( ) ;
net . minecraft . network . play . server . S28PacketEffect packet = new net . minecraft . network . play . server . S28PacketEffect ( packetData , loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) , data , false ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( packet ) ;
}
@Override
public < T > void playEffect ( Location loc , Effect effect , T data ) {
if ( data ! = null ) {
Validate . isTrue ( data . getClass ( ) . equals ( effect . getData ( ) ) , "Wrong kind of data for this effect!" ) ;
} else {
Validate . isTrue ( effect . getData ( ) = = null , "Wrong kind of data for this effect!" ) ;
}
int datavalue = data = = null ? 0 : CraftEffect . getDataValue ( effect , data ) ;
playEffect ( loc , effect , datavalue ) ;
}
@Override
public void sendBlockChange ( Location loc , Material material , byte data ) {
sendBlockChange ( loc , material . getId ( ) , data ) ;
}
@Override
public void sendBlockChange ( Location loc , int material , byte data ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
S23PacketBlockChange packet = new S23PacketBlockChange ( loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) , ( ( CraftWorld ) loc . getWorld ( ) ) . getHandle ( ) ) ;
packet . field_148883_d = CraftMagicNumbers . getBlock ( material ) ;
packet . field_148884_e = data ;
getHandle ( ) . playerNetServerHandler . sendPacket ( packet ) ;
}
@Override
public void sendSignChange ( Location loc , String [ ] lines ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) {
return ;
}
if ( lines = = null ) {
lines = new String [ 4 ] ;
}
Validate . notNull ( loc , "Location can not be null" ) ;
if ( lines . length < 4 ) {
throw new IllegalArgumentException ( "Must have at least 4 lines" ) ;
}
// Limit to 15 chars per line and set null lines to blank
String [ ] astring = CraftSign . sanitizeLines ( lines ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( new S33PacketUpdateSign ( loc . getBlockX ( ) , loc . getBlockY ( ) , loc . getBlockZ ( ) , astring ) ) ;
}
@Override
public boolean sendChunkChange ( Location loc , int sx , int sy , int sz , byte [ ] data ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return false ;
/ *
int x = loc . getBlockX ( ) ;
int y = loc . getBlockY ( ) ;
int z = loc . getBlockZ ( ) ;
int cx = x > > 4 ;
int cz = z > > 4 ;
if ( sx < = 0 | | sy < = 0 | | sz < = 0 ) {
return false ;
}
if ( ( x + sx - 1 ) > > 4 ! = cx | | ( z + sz - 1 ) > > 4 ! = cz | | y < 0 | | y + sy > 128 ) {
return false ;
}
if ( data . length ! = ( sx * sy * sz * 5 ) / 2 ) {
return false ;
}
Packet51MapChunk packet = new Packet51MapChunk ( x , y , z , sx , sy , sz , data ) ;
getHandle ( ) . playerConnection . sendPacket ( packet ) ;
return true ;
* /
throw new NotImplementedException ( "Chunk changes do not yet work" ) ; // TODO: Chunk changes.
}
@Override
public void sendMap ( MapView map ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
RenderData data = ( ( CraftMapView ) map ) . render ( this ) ;
for ( int x = 0 ; x < 128 ; + + x ) {
byte [ ] bytes = new byte [ 131 ] ;
bytes [ 1 ] = ( byte ) x ;
for ( int y = 0 ; y < 128 ; + + y ) {
bytes [ y + 3 ] = data . buffer [ y * 128 + x ] ;
}
net . minecraft . network . play . server . S34PacketMaps packet = new net . minecraft . network . play . server . S34PacketMaps ( map . getId ( ) , bytes ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( packet ) ;
}
}
@Override
public boolean teleport ( Location location , PlayerTeleportEvent . TeleportCause cause ) {
net . minecraft . entity . player . EntityPlayerMP entity = getHandle ( ) ;
if ( getHealth ( ) = = 0 | | entity . isDead ) {
return false ;
}
if ( entity . playerNetServerHandler = = null | | entity . playerNetServerHandler . isDisconnected ( ) ) {
return false ;
}
// Spigot Start
// if (entity.vehicle != null || entity.passenger != null) {
// return false;
// }
// Spigot End
// From = Players current Location
Location from = this . getLocation ( ) ;
// To = Players new Location if Teleport is Successful
Location to = location ;
// Create & Call the Teleport Event.
PlayerTeleportEvent event = new PlayerTeleportEvent ( this , from , to , cause ) ;
server . getPluginManager ( ) . callEvent ( event ) ;
// Return False to inform the Plugin that the Teleport was unsuccessful/cancelled.
if ( event . isCancelled ( ) ) {
return false ;
}
// Spigot Start
eject ( ) ;
leaveVehicle ( ) ;
// Spigot End
// Update the From Location
from = event . getFrom ( ) ;
// Grab the new To Location dependent on whether the event was cancelled.
to = event . getTo ( ) ;
// Grab the To and From World Handles.
net . minecraft . world . WorldServer fromWorld = ( ( CraftWorld ) from . getWorld ( ) ) . getHandle ( ) ;
net . minecraft . world . WorldServer toWorld = ( ( CraftWorld ) to . getWorld ( ) ) . getHandle ( ) ;
// Close any foreign inventory
if ( getHandle ( ) . openContainer ! = getHandle ( ) . inventoryContainer ) {
getHandle ( ) . closeScreen ( ) ;
}
// Check if the fromWorld and toWorld are the same.
if ( fromWorld = = toWorld ) {
entity . playerNetServerHandler . teleport ( to ) ;
} else {
server . getHandle ( ) . respawnPlayer ( entity , toWorld . dimension , false , to ) ; // Cauldron
}
return true ;
}
@Override
public void setSneaking ( boolean sneak ) {
getHandle ( ) . setSneaking ( sneak ) ;
}
@Override
public boolean isSneaking ( ) {
return getHandle ( ) . isSneaking ( ) ;
}
@Override
public boolean isSprinting ( ) {
return getHandle ( ) . isSprinting ( ) ;
}
@Override
public void setSprinting ( boolean sprinting ) {
getHandle ( ) . setSprinting ( sprinting ) ;
}
@Override
public void loadData ( ) {
server . getHandle ( ) . playerNBTManagerObj . readPlayerData ( getHandle ( ) ) ;
}
@Override
public void saveData ( ) {
server . getHandle ( ) . playerNBTManagerObj . writePlayerData ( getHandle ( ) ) ;
}
@Deprecated
@Override
public void updateInventory ( ) {
getHandle ( ) . sendContainerToPlayer ( getHandle ( ) . openContainer ) ;
}
@Override
public void setSleepingIgnored ( boolean isSleeping ) {
getHandle ( ) . fauxSleeping = isSleeping ;
( ( CraftWorld ) getWorld ( ) ) . getHandle ( ) . checkSleepStatus ( ) ;
}
@Override
public boolean isSleepingIgnored ( ) {
return getHandle ( ) . fauxSleeping ;
}
@Override
public void awardAchievement ( Achievement achievement ) {
Validate . notNull ( achievement , "Achievement cannot be null" ) ;
if ( achievement . hasParent ( ) & & ! hasAchievement ( achievement . getParent ( ) ) ) {
awardAchievement ( achievement . getParent ( ) ) ;
}
getHandle ( ) . func_147099_x ( ) . func_150873_a ( getHandle ( ) , CraftStatistic . getNMSAchievement ( achievement ) , 1 ) ;
getHandle ( ) . func_147099_x ( ) . func_150884_b ( getHandle ( ) ) ;
}
@Override
public void removeAchievement ( Achievement achievement ) {
Validate . notNull ( achievement , "Achievement cannot be null" ) ;
for ( Achievement achieve : Achievement . values ( ) ) {
if ( achieve . getParent ( ) = = achievement & & hasAchievement ( achieve ) ) {
removeAchievement ( achieve ) ;
}
}
getHandle ( ) . func_147099_x ( ) . func_150873_a ( getHandle ( ) , CraftStatistic . getNMSAchievement ( achievement ) , 0 ) ;
}
@Override
public boolean hasAchievement ( Achievement achievement ) {
Validate . notNull ( achievement , "Achievement cannot be null" ) ;
return getHandle ( ) . func_147099_x ( ) . hasAchievementUnlocked ( CraftStatistic . getNMSAchievement ( achievement ) ) ;
}
@Override
public void incrementStatistic ( Statistic statistic ) {
incrementStatistic ( statistic , 1 ) ;
}
@Override
public void decrementStatistic ( Statistic statistic ) {
decrementStatistic ( statistic , 1 ) ;
}
@Override
public int getStatistic ( Statistic statistic ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . UNTYPED , "Must supply additional paramater for this statistic" ) ;
return getHandle ( ) . func_147099_x ( ) . writeStat ( CraftStatistic . getNMSStatistic ( statistic ) ) ;
}
@Override
public void incrementStatistic ( Statistic statistic , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , getStatistic ( statistic ) + amount ) ;
}
@Override
public void decrementStatistic ( Statistic statistic , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , getStatistic ( statistic ) - amount ) ;
}
@Override
public void setStatistic ( Statistic statistic , int newValue ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . UNTYPED , "Must supply additional paramater for this statistic" ) ;
Validate . isTrue ( newValue > = 0 , "Value must be greater than or equal to 0" ) ;
net . minecraft . stats . StatBase nmsStatistic = CraftStatistic . getNMSStatistic ( statistic ) ;
getHandle ( ) . func_147099_x ( ) . func_150873_a ( getHandle ( ) , nmsStatistic , newValue ) ;
}
@Override
public void incrementStatistic ( Statistic statistic , Material material ) {
incrementStatistic ( statistic , material , 1 ) ;
}
@Override
public void decrementStatistic ( Statistic statistic , Material material ) {
decrementStatistic ( statistic , material , 1 ) ;
}
@Override
public int getStatistic ( Statistic statistic , Material material ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . notNull ( material , "Material cannot be null" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . BLOCK | | statistic . getType ( ) = = Type . ITEM , "This statistic does not take a Material parameter" ) ;
net . minecraft . stats . StatBase nmsStatistic = CraftStatistic . getMaterialStatistic ( statistic , material ) ;
Validate . notNull ( nmsStatistic , "The supplied Material does not have a corresponding statistic" ) ;
return getHandle ( ) . func_147099_x ( ) . writeStat ( nmsStatistic ) ;
}
@Override
public void incrementStatistic ( Statistic statistic , Material material , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , material , getStatistic ( statistic , material ) + amount ) ;
}
@Override
public void decrementStatistic ( Statistic statistic , Material material , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , material , getStatistic ( statistic , material ) - amount ) ;
}
@Override
public void setStatistic ( Statistic statistic , Material material , int newValue ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . notNull ( material , "Material cannot be null" ) ;
Validate . isTrue ( newValue > = 0 , "Value must be greater than or equal to 0" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . BLOCK | | statistic . getType ( ) = = Type . ITEM , "This statistic does not take a Material parameter" ) ;
net . minecraft . stats . StatBase nmsStatistic = CraftStatistic . getMaterialStatistic ( statistic , material ) ;
Validate . notNull ( nmsStatistic , "The supplied Material does not have a corresponding statistic" ) ;
getHandle ( ) . func_147099_x ( ) . func_150873_a ( getHandle ( ) , nmsStatistic , newValue ) ;
}
@Override
public void incrementStatistic ( Statistic statistic , EntityType entityType ) {
incrementStatistic ( statistic , entityType , 1 ) ;
}
@Override
public void decrementStatistic ( Statistic statistic , EntityType entityType ) {
decrementStatistic ( statistic , entityType , 1 ) ;
}
@Override
public int getStatistic ( Statistic statistic , EntityType entityType ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . notNull ( entityType , "EntityType cannot be null" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . ENTITY , "This statistic does not take an EntityType parameter" ) ;
net . minecraft . stats . StatBase nmsStatistic = CraftStatistic . getEntityStatistic ( statistic , entityType ) ;
Validate . notNull ( nmsStatistic , "The supplied EntityType does not have a corresponding statistic" ) ;
return getHandle ( ) . func_147099_x ( ) . writeStat ( nmsStatistic ) ;
}
@Override
public void incrementStatistic ( Statistic statistic , EntityType entityType , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , entityType , getStatistic ( statistic , entityType ) + amount ) ;
}
@Override
public void decrementStatistic ( Statistic statistic , EntityType entityType , int amount ) {
Validate . isTrue ( amount > 0 , "Amount must be greater than 0" ) ;
setStatistic ( statistic , entityType , getStatistic ( statistic , entityType ) - amount ) ;
}
@Override
public void setStatistic ( Statistic statistic , EntityType entityType , int newValue ) {
Validate . notNull ( statistic , "Statistic cannot be null" ) ;
Validate . notNull ( entityType , "EntityType cannot be null" ) ;
Validate . isTrue ( newValue > = 0 , "Value must be greater than or equal to 0" ) ;
Validate . isTrue ( statistic . getType ( ) = = Type . ENTITY , "This statistic does not take an EntityType parameter" ) ;
net . minecraft . stats . StatBase nmsStatistic = CraftStatistic . getEntityStatistic ( statistic , entityType ) ;
Validate . notNull ( nmsStatistic , "The supplied EntityType does not have a corresponding statistic" ) ;
getHandle ( ) . func_147099_x ( ) . func_150873_a ( getHandle ( ) , nmsStatistic , newValue ) ;
}
@Override
public void setPlayerTime ( long time , boolean relative ) {
getHandle ( ) . timeOffset = time ;
getHandle ( ) . relativeTime = relative ;
}
@Override
public long getPlayerTimeOffset ( ) {
return getHandle ( ) . timeOffset ;
}
@Override
public long getPlayerTime ( ) {
return getHandle ( ) . getPlayerTime ( ) ;
}
@Override
public boolean isPlayerTimeRelative ( ) {
return getHandle ( ) . relativeTime ;
}
@Override
public void resetPlayerTime ( ) {
setPlayerTime ( 0 , true ) ;
}
@Override
public void setPlayerWeather ( WeatherType type ) {
getHandle ( ) . setPlayerWeather ( type , true ) ;
}
@Override
public WeatherType getPlayerWeather ( ) {
return getHandle ( ) . getPlayerWeather ( ) ;
}
@Override
public void resetPlayerWeather ( ) {
getHandle ( ) . resetPlayerWeather ( ) ;
}
@Override
public boolean isBanned ( ) {
return server . getBanList ( BanList . Type . NAME ) . isBanned ( getName ( ) ) ;
}
@Override
public void setBanned ( boolean value ) {
if ( value ) {
server . getBanList ( BanList . Type . NAME ) . addBan ( getName ( ) , null , null , null ) ;
} else {
server . getBanList ( BanList . Type . NAME ) . pardon ( getName ( ) ) ;
}
}
@Override
public boolean isWhitelisted ( ) {
return server . getHandle ( ) . func_152607_e ( getProfile ( ) ) ;
}
@Override
public void setWhitelisted ( boolean value ) {
if ( value ) {
server . getHandle ( ) . func_152601_d ( getProfile ( ) ) ;
} else {
server . getHandle ( ) . func_152597_c ( getProfile ( ) ) ;
}
}
@Override
public void setGameMode ( GameMode mode ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
if ( mode = = null ) {
throw new IllegalArgumentException ( "Mode cannot be null" ) ;
}
if ( mode ! = getGameMode ( ) ) {
PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent ( this , mode ) ;
server . getPluginManager ( ) . callEvent ( event ) ;
if ( event . isCancelled ( ) ) {
return ;
}
getHandle ( ) . theItemInWorldManager . setGameType ( net . minecraft . world . WorldSettings . GameType . getByID ( mode . getValue ( ) ) ) ;
getHandle ( ) . fallDistance = 0 ;
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S2BPacketChangeGameState ( 3 , mode . getValue ( ) ) ) ;
}
}
@Override
public GameMode getGameMode ( ) {
return GameMode . getByValue ( getHandle ( ) . theItemInWorldManager . getGameType ( ) . getID ( ) ) ;
}
public void giveExp ( int exp ) {
getHandle ( ) . addExperience ( exp ) ;
}
public void giveExpLevels ( int levels ) {
getHandle ( ) . addExperienceLevel ( levels ) ;
}
public float getExp ( ) {
return getHandle ( ) . experience ;
}
public void setExp ( float exp ) {
getHandle ( ) . experience = exp ;
getHandle ( ) . lastExperience = - 1 ;
}
public int getLevel ( ) {
return getHandle ( ) . experienceLevel ;
}
public void setLevel ( int level ) {
getHandle ( ) . experienceLevel = level ;
getHandle ( ) . lastExperience = - 1 ;
}
public int getTotalExperience ( ) {
return getHandle ( ) . experienceTotal ;
}
public void setTotalExperience ( int exp ) {
getHandle ( ) . experienceTotal = exp ;
}
public float getExhaustion ( ) {
return getHandle ( ) . getFoodStats ( ) . foodExhaustionLevel ;
}
public void setExhaustion ( float value ) {
getHandle ( ) . getFoodStats ( ) . foodExhaustionLevel = value ;
}
public float getSaturation ( ) {
return getHandle ( ) . getFoodStats ( ) . foodSaturationLevel ;
}
public void setSaturation ( float value ) {
getHandle ( ) . getFoodStats ( ) . foodSaturationLevel = value ;
}
public int getFoodLevel ( ) {
return getHandle ( ) . getFoodStats ( ) . foodLevel ;
}
public void setFoodLevel ( int value ) {
getHandle ( ) . getFoodStats ( ) . foodLevel = value ;
}
public Location getBedSpawnLocation ( ) {
World world = getServer ( ) . getWorld ( getHandle ( ) . spawnWorld ) ;
net . minecraft . util . ChunkCoordinates bed = getHandle ( ) . getBedLocation ( ) ;
if ( world ! = null & & bed ! = null ) {
bed = net . minecraft . entity . player . EntityPlayer . verifyRespawnCoordinates ( ( ( CraftWorld ) world ) . getHandle ( ) , bed , getHandle ( ) . isSpawnForced ( ) ) ;
if ( bed ! = null ) {
return new Location ( world , bed . posX , bed . posY , bed . posZ ) ;
}
}
return null ;
}
public void setBedSpawnLocation ( Location location ) {
setBedSpawnLocation ( location , false ) ;
}
public void setBedSpawnLocation ( Location location , boolean override ) {
if ( location = = null ) {
getHandle ( ) . setSpawnChunk ( null , override ) ;
} else {
getHandle ( ) . setSpawnChunk ( new net . minecraft . util . ChunkCoordinates ( location . getBlockX ( ) , location . getBlockY ( ) , location . getBlockZ ( ) ) , override ) ;
getHandle ( ) . spawnWorld = location . getWorld ( ) . getName ( ) ;
}
}
public void hidePlayer ( Player player ) {
Validate . notNull ( player , "hidden player cannot be null" ) ;
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
if ( equals ( player ) ) return ;
if ( hiddenPlayers . contains ( player . getUniqueId ( ) ) ) return ;
hiddenPlayers . add ( player . getUniqueId ( ) ) ;
//remove this player from the hidden player's EntityTrackerEntry
net . minecraft . entity . EntityTracker tracker = ( ( net . minecraft . world . WorldServer ) entity . worldObj ) . theEntityTracker ;
net . minecraft . entity . player . EntityPlayerMP other = ( ( CraftPlayer ) player ) . getHandle ( ) ;
net . minecraft . entity . EntityTrackerEntry entry = ( net . minecraft . entity . EntityTrackerEntry ) tracker . trackedEntityIDs . lookup ( other . getEntityId ( ) ) ;
if ( entry ! = null ) {
entry . removePlayerFromTracker ( getHandle ( ) ) ;
}
//remove the hidden player from this player user list
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S38PacketPlayerListItem ( player . getPlayerListName ( ) , false , 9999 ) ) ;
}
public void showPlayer ( Player player ) {
Validate . notNull ( player , "shown player cannot be null" ) ;
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
if ( equals ( player ) ) return ;
if ( ! hiddenPlayers . contains ( player . getUniqueId ( ) ) ) return ;
hiddenPlayers . remove ( player . getUniqueId ( ) ) ;
EntityTracker tracker = ( ( WorldServer ) entity . worldObj ) . theEntityTracker ;
EntityPlayerMP other = ( ( CraftPlayer ) player ) . getHandle ( ) ;
EntityTrackerEntry entry = ( EntityTrackerEntry ) tracker . trackedEntityIDs . lookup ( other . getEntityId ( ) ) ;
if ( entry ! = null ) {
entry . removePlayerFromTracker ( getHandle ( ) ) ;
}
getHandle ( ) . playerNetServerHandler . sendPacket ( new S38PacketPlayerListItem ( player . getPlayerListName ( ) , false , 9999 ) ) ;
}
public void removeDisconnectingPlayer ( Player player ) {
hiddenPlayers . remove ( player . getUniqueId ( ) ) ;
}
public boolean canSee ( Player player ) {
return ! hiddenPlayers . contains ( player . getUniqueId ( ) ) ;
}
public Map < String , Object > serialize ( ) {
Map < String , Object > result = new LinkedHashMap < String , Object > ( ) ;
result . put ( "name" , getName ( ) ) ;
return result ;
}
public Player getPlayer ( ) {
return this ;
}
@Override
public net . minecraft . entity . player . EntityPlayerMP getHandle ( ) {
return ( net . minecraft . entity . player . EntityPlayerMP ) entity ;
}
public void setHandle ( final net . minecraft . entity . player . EntityPlayerMP entity ) {
super . setHandle ( entity ) ;
}
@Override
public String toString ( ) {
return "CraftPlayer{" + "name=" + getName ( ) + '}' ;
}
@Override
public int hashCode ( ) {
if ( hash = = 0 | | hash = = 485 ) {
hash = 97 * 5 + ( this . getName ( ) ! = null ? this . getName ( ) . toLowerCase ( ) . hashCode ( ) : 0 ) ;
}
return hash ;
}
public long getFirstPlayed ( ) {
return firstPlayed ;
}
public long getLastPlayed ( ) {
return lastPlayed ;
}
public boolean hasPlayedBefore ( ) {
return hasPlayedBefore ;
}
public void setFirstPlayed ( long firstPlayed ) {
this . firstPlayed = firstPlayed ;
}
public void readExtraData ( net . minecraft . nbt . NBTTagCompound nbttagcompound ) {
hasPlayedBefore = true ;
if ( nbttagcompound . hasKey ( "bukkit" ) ) {
net . minecraft . nbt . NBTTagCompound data = nbttagcompound . getCompoundTag ( "bukkit" ) ;
if ( data . hasKey ( "firstPlayed" ) ) {
firstPlayed = data . getLong ( "firstPlayed" ) ;
lastPlayed = data . getLong ( "lastPlayed" ) ;
}
if ( data . hasKey ( "newExp" ) ) {
net . minecraft . entity . player . EntityPlayerMP handle = getHandle ( ) ;
handle . newExp = data . getInteger ( "newExp" ) ;
handle . newTotalExp = data . getInteger ( "newTotalExp" ) ;
handle . newLevel = data . getInteger ( "newLevel" ) ;
handle . expToDrop = data . getInteger ( "expToDrop" ) ;
handle . keepLevel = data . getBoolean ( "keepLevel" ) ;
}
}
}
public void setExtraData ( net . minecraft . nbt . NBTTagCompound nbttagcompound ) {
if ( ! nbttagcompound . hasKey ( "bukkit" ) ) {
nbttagcompound . setTag ( "bukkit" , new net . minecraft . nbt . NBTTagCompound ( ) ) ;
}
net . minecraft . nbt . NBTTagCompound data = nbttagcompound . getCompoundTag ( "bukkit" ) ;
net . minecraft . entity . player . EntityPlayerMP handle = getHandle ( ) ;
data . setInteger ( "newExp" , handle . newExp ) ;
data . setInteger ( "newTotalExp" , handle . newTotalExp ) ;
data . setInteger ( "newLevel" , handle . newLevel ) ;
data . setInteger ( "expToDrop" , handle . expToDrop ) ;
data . setBoolean ( "keepLevel" , handle . keepLevel ) ;
data . setLong ( "firstPlayed" , getFirstPlayed ( ) ) ;
data . setLong ( "lastPlayed" , System . currentTimeMillis ( ) ) ;
data . setString ( "lastKnownName" , handle . getCommandSenderName ( ) ) ;
}
public boolean beginConversation ( Conversation conversation ) {
return conversationTracker . beginConversation ( conversation ) ;
}
public void abandonConversation ( Conversation conversation ) {
conversationTracker . abandonConversation ( conversation , new ConversationAbandonedEvent ( conversation , new ManuallyAbandonedConversationCanceller ( ) ) ) ;
}
public void abandonConversation ( Conversation conversation , ConversationAbandonedEvent details ) {
conversationTracker . abandonConversation ( conversation , details ) ;
}
public void acceptConversationInput ( String input ) {
conversationTracker . acceptConversationInput ( input ) ;
}
public boolean isConversing ( ) {
return conversationTracker . isConversing ( ) ;
}
public void sendPluginMessage ( Plugin source , String channel , byte [ ] message ) {
StandardMessenger . validatePluginMessage ( server . getMessenger ( ) , source , channel , message ) ;
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
if ( channels . contains ( channel ) ) {
net . minecraft . network . play . server . S3FPacketCustomPayload packet = new net . minecraft . network . play . server . S3FPacketCustomPayload ( channel , message ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( packet ) ;
}
}
public void setTexturePack ( String url ) {
setResourcePack ( url ) ;
}
@Override
public void setResourcePack ( String url ) {
Validate . notNull ( url , "Resource pack URL cannot be null" ) ;
getHandle ( ) . requestTexturePackLoad ( url ) ; // should be setResourcePack
}
public void addChannel ( String channel ) {
com . google . common . base . Preconditions . checkState ( channels . size ( ) < 128 , "Too many channels registered" ) ; // Spigot
if ( channels . add ( channel ) ) {
server . getPluginManager ( ) . callEvent ( new PlayerRegisterChannelEvent ( this , channel ) ) ;
}
}
public void removeChannel ( String channel ) {
if ( channels . remove ( channel ) ) {
server . getPluginManager ( ) . callEvent ( new PlayerUnregisterChannelEvent ( this , channel ) ) ;
}
}
public Set < String > getListeningPluginChannels ( ) {
return ImmutableSet . copyOf ( channels ) ;
}
public void sendSupportedChannels ( ) {
if ( getHandle ( ) . playerNetServerHandler = = null ) return ;
Set < String > listening = server . getMessenger ( ) . getIncomingChannels ( ) ;
if ( ! listening . isEmpty ( ) ) {
ByteArrayOutputStream stream = new ByteArrayOutputStream ( ) ;
for ( String channel : listening ) {
try {
stream . write ( channel . getBytes ( "UTF8" ) ) ;
stream . write ( ( byte ) 0 ) ;
} catch ( IOException ex ) {
Logger . getLogger ( CraftPlayer . class . getName ( ) ) . log ( Level . SEVERE , "Could not send Plugin Channel REGISTER to " + getName ( ) , ex ) ;
}
}
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S3FPacketCustomPayload ( "REGISTER" , stream . toByteArray ( ) ) ) ;
}
}
@Override
public EntityType getType ( ) {
return EntityType . PLAYER ;
}
@Override
public void setMetadata ( String metadataKey , MetadataValue newMetadataValue ) {
server . getPlayerMetadata ( ) . setMetadata ( this , metadataKey , newMetadataValue ) ;
}
@Override
public List < MetadataValue > getMetadata ( String metadataKey ) {
return server . getPlayerMetadata ( ) . getMetadata ( this , metadataKey ) ;
}
@Override
public boolean hasMetadata ( String metadataKey ) {
return server . getPlayerMetadata ( ) . hasMetadata ( this , metadataKey ) ;
}
@Override
public void removeMetadata ( String metadataKey , Plugin owningPlugin ) {
server . getPlayerMetadata ( ) . removeMetadata ( this , metadataKey , owningPlugin ) ;
}
@Override
public boolean setWindowProperty ( Property prop , int value ) {
net . minecraft . inventory . Container container = getHandle ( ) . openContainer ;
if ( container . getBukkitView ( ) . getType ( ) ! = prop . getType ( ) ) {
return false ;
}
getHandle ( ) . sendProgressBarUpdate ( container , prop . getId ( ) , value ) ;
return true ;
}
public void disconnect ( String reason ) {
conversationTracker . abandonAllConversations ( ) ;
perm . clearPermissions ( ) ;
}
public boolean isFlying ( ) {
return getHandle ( ) . capabilities . isFlying ;
}
public void setFlying ( boolean value ) {
if ( ! getAllowFlight ( ) & & value ) {
throw new IllegalArgumentException ( "Cannot make player fly if getAllowFlight() is false" ) ;
}
getHandle ( ) . capabilities . isFlying = value ;
getHandle ( ) . sendPlayerAbilities ( ) ;
}
public boolean getAllowFlight ( ) {
return getHandle ( ) . capabilities . allowFlying ;
}
public void setAllowFlight ( boolean value ) {
if ( isFlying ( ) & & ! value ) {
getHandle ( ) . capabilities . isFlying = false ;
}
getHandle ( ) . capabilities . allowFlying = value ;
getHandle ( ) . sendPlayerAbilities ( ) ;
}
@Override
public int getNoDamageTicks ( ) {
if ( getHandle ( ) . field_147101_bU > 0 ) {
return Math . max ( getHandle ( ) . field_147101_bU , getHandle ( ) . hurtResistantTime ) ;
} else {
return getHandle ( ) . hurtResistantTime ;
}
}
public void setFlySpeed ( float value ) {
validateSpeed ( value ) ;
net . minecraft . entity . player . EntityPlayerMP player = getHandle ( ) ;
player . capabilities . flySpeed = Math . max ( value , 0 . 0001f ) / 2f ; // Spigot
player . sendPlayerAbilities ( ) ;
}
public void setWalkSpeed ( float value ) {
validateSpeed ( value ) ;
net . minecraft . entity . player . EntityPlayerMP player = getHandle ( ) ;
player . capabilities . walkSpeed = Math . max ( value , 0 . 0001f ) / 2f ; // Spigot
player . sendPlayerAbilities ( ) ;
}
public float getFlySpeed ( ) {
return getHandle ( ) . capabilities . flySpeed * 2f ;
}
public float getWalkSpeed ( ) {
return getHandle ( ) . capabilities . walkSpeed * 2f ;
}
private void validateSpeed ( float value ) {
if ( value < 0 ) {
if ( value < - 1f ) {
throw new IllegalArgumentException ( value + " is too low" ) ;
}
} else {
if ( value > 1f ) {
throw new IllegalArgumentException ( value + " is too high" ) ;
}
}
}
@Override
public void setMaxHealth ( double amount ) {
super . setMaxHealth ( amount ) ;
this . health = Math . min ( this . health , health ) ;
getHandle ( ) . setPlayerHealthUpdated ( ) ;
}
@Override
public void resetMaxHealth ( ) {
super . resetMaxHealth ( ) ;
getHandle ( ) . setPlayerHealthUpdated ( ) ;
}
public CraftScoreboard getScoreboard ( ) {
return this . server . getScoreboardManager ( ) . getPlayerBoard ( this ) ;
}
public void setScoreboard ( Scoreboard scoreboard ) {
Validate . notNull ( scoreboard , "Scoreboard cannot be null" ) ;
net . minecraft . network . NetHandlerPlayServer playerConnection = getHandle ( ) . playerNetServerHandler ;
if ( playerConnection = = null ) {
throw new IllegalStateException ( "Cannot set scoreboard yet" ) ;
}
if ( playerConnection . isDisconnected ( ) ) {
// throw new IllegalStateException("Cannot set scoreboard for invalid CraftPlayer"); // Spigot - remove this as Mojang's semi asynchronous Netty implementation can lead to races
}
this . server . getScoreboardManager ( ) . setPlayerBoard ( this , scoreboard ) ;
}
public void setHealthScale ( double value ) {
Validate . isTrue ( ( float ) value > 0F , "Must be greater than 0" ) ;
healthScale = value ;
scaledHealth = true ;
updateScaledHealth ( ) ;
}
public double getHealthScale ( ) {
return healthScale ;
}
public void setHealthScaled ( boolean scale ) {
if ( scaledHealth ! = ( scaledHealth = scale ) ) {
updateScaledHealth ( ) ;
}
}
public boolean isHealthScaled ( ) {
return scaledHealth ;
}
public float getScaledHealth ( ) {
return ( float ) ( isHealthScaled ( ) ? getHealth ( ) * getHealthScale ( ) / getMaxHealth ( ) : getHealth ( ) ) ;
}
@Override
public double getHealth ( ) {
return health ;
}
public void setRealHealth ( double health ) {
this . health = health ;
}
public void updateScaledHealth ( ) {
net . minecraft . entity . ai . attributes . ServersideAttributeMap attributemapserver = ( net . minecraft . entity . ai . attributes . ServersideAttributeMap ) getHandle ( ) . getAttributeMap ( ) ;
Set set = attributemapserver . getAttributeInstanceSet ( ) ;
injectScaledMaxHealth ( set , true ) ;
getHandle ( ) . getDataWatcher ( ) . updateObject ( 6 , ( float ) getScaledHealth ( ) ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S06PacketUpdateHealth ( getScaledHealth ( ) , getHandle ( ) . getFoodStats ( ) . getFoodLevel ( ) , getHandle ( ) . getFoodStats ( ) . getSaturationLevel ( ) ) ) ;
getHandle ( ) . playerNetServerHandler . sendPacket ( new net . minecraft . network . play . server . S20PacketEntityProperties ( getHandle ( ) . getEntityId ( ) , set ) ) ;
set . clear ( ) ;
getHandle ( ) . maxHealthCache = getMaxHealth ( ) ;
}
public void injectScaledMaxHealth ( Collection collection , boolean force ) {
if ( ! scaledHealth & & ! force ) {
return ;
}
for ( Object genericInstance : collection ) {
net . minecraft . entity . ai . attributes . IAttribute attribute = ( ( net . minecraft . entity . ai . attributes . IAttributeInstance ) genericInstance ) . getAttribute ( ) ;
if ( attribute . getAttributeUnlocalizedName ( ) . equals ( "generic.maxHealth" ) ) {
collection . remove ( genericInstance ) ;
break ;
}
continue ;
}
collection . add ( new net . minecraft . entity . ai . attributes . ModifiableAttributeInstance ( getHandle ( ) . getAttributeMap ( ) , ( new net . minecraft . entity . ai . attributes . RangedAttribute ( "generic.maxHealth" , scaledHealth ? healthScale : getMaxHealth ( ) , 0 . 0D , Float . MAX_VALUE ) ) . setDescription ( "Max Health" ) . setShouldWatch ( true ) ) ) ;
}
// Spigot start
private final Player . Spigot spigot = new Player . Spigot ( )
{
@Override
public InetSocketAddress getRawAddress ( )
{
return ( InetSocketAddress ) getHandle ( ) . playerNetServerHandler . netManager . getRawAddress ( ) ;
}
@Override
public boolean getCollidesWithEntities ( )
{
return getHandle ( ) . collidesWithEntities ;
}
@Override
public void setCollidesWithEntities ( boolean collides )
{
getHandle ( ) . collidesWithEntities = collides ;
getHandle ( ) . preventEntitySpawning = collides ; // First boolean of Entity
}
@Override
public void respawn ( )
{
if ( getHealth ( ) < = 0 & & isOnline ( ) )
{
server . getServer ( ) . getConfigurationManager ( ) . respawnPlayer ( getHandle ( ) , 0 , false ) ;
}
}
@Override
public String getLocale ( )
{
return getHandle ( ) . translator ;
}
} ;
public Player . Spigot spigot ( )
{
return spigot ;
}
// Spigot end
}