You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1344 lines
47 KiB
1344 lines
47 KiB
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 |
|
} |