1454 lines
50 KiB
Java
1454 lines
50 KiB
Java
package org.bukkit.craftbukkit.entity;
|
|
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.io.BaseEncoding;
|
|
import com.mojang.authlib.GameProfile;
|
|
import io.netty.buffer.Unpooled;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.SocketAddress;
|
|
import java.util.ArrayList;
|
|
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 net.minecraft.server.*;
|
|
import net.minecraft.server.PacketPlayOutTitle.EnumTitleAction;
|
|
|
|
import org.apache.commons.lang.Validate;
|
|
import org.apache.commons.lang.NotImplementedException;
|
|
import org.bukkit.*;
|
|
import org.bukkit.Achievement;
|
|
import org.bukkit.BanList;
|
|
import org.bukkit.Statistic;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.Statistic.Type;
|
|
import org.bukkit.World;
|
|
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.CraftParticle;
|
|
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.advancement.CraftAdvancement;
|
|
import org.bukkit.craftbukkit.advancement.CraftAdvancementProgress;
|
|
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.MapCursor;
|
|
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, EntityPlayer entity) {
|
|
super(server, entity);
|
|
|
|
firstPlayed = System.currentTimeMillis();
|
|
}
|
|
|
|
public GameProfile getProfile() {
|
|
return getHandle().getProfile();
|
|
}
|
|
|
|
@Override
|
|
public boolean isOp() {
|
|
return server.getHandle().isOp(getProfile());
|
|
}
|
|
|
|
@Override
|
|
public void setOp(boolean value) {
|
|
if (value == isOp()) return;
|
|
|
|
if (value) {
|
|
server.getHandle().addOp(getProfile());
|
|
} else {
|
|
server.getHandle().removeOp(getProfile());
|
|
}
|
|
|
|
perm.recalculatePermissions();
|
|
}
|
|
|
|
public boolean isOnline() {
|
|
return server.getPlayer(getUniqueId()) != null;
|
|
}
|
|
|
|
public InetSocketAddress getAddress() {
|
|
if (getHandle().playerConnection == null) return null;
|
|
|
|
SocketAddress addr = getHandle().playerConnection.networkManager.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().playerConnection == null) return;
|
|
|
|
for (IChatBaseComponent component : CraftChatMessage.fromString(message)) {
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutChat(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 == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName, EnumChatFormat.WHITE);
|
|
}
|
|
|
|
@Override
|
|
public void setPlayerListName(String name) {
|
|
if (name == null) {
|
|
name = getName();
|
|
}
|
|
getHandle().listName = name.equals(getName()) ? null : CraftChatMessage.fromString(name)[0];
|
|
for (EntityPlayer player : (List<EntityPlayer>)server.getHandle().players) {
|
|
if (player.getBukkitEntity().canSee(this)) {
|
|
player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle()));
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (!(obj instanceof OfflinePlayer)) {
|
|
return false;
|
|
}
|
|
OfflinePlayer other = (OfflinePlayer) obj;
|
|
if ((this.getUniqueId() == null) || (other.getUniqueId() == null)) {
|
|
return false;
|
|
}
|
|
|
|
boolean uuidEquals = this.getUniqueId().equals(other.getUniqueId());
|
|
boolean idEquals = true;
|
|
|
|
if (other instanceof CraftPlayer) {
|
|
idEquals = this.getEntityId() == ((CraftPlayer) other).getEntityId();
|
|
}
|
|
|
|
return uuidEquals && idEquals;
|
|
}
|
|
|
|
@Override
|
|
public void kickPlayer(String message) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
getHandle().playerConnection.disconnect(message == null ? "" : message);
|
|
}
|
|
|
|
@Override
|
|
public void setCompassTarget(Location loc) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
// Do not directly assign here, from the packethandler we'll assign it.
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutSpawnPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())));
|
|
}
|
|
|
|
@Override
|
|
public Location getCompassTarget() {
|
|
return getHandle().compassTarget;
|
|
}
|
|
|
|
@Override
|
|
public void chat(String msg) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
getHandle().playerConnection.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().playerConnection == null) return;
|
|
|
|
String instrumentName = null;
|
|
switch (instrument) {
|
|
case 0:
|
|
instrumentName = "harp";
|
|
break;
|
|
case 1:
|
|
instrumentName = "basedrum";
|
|
break;
|
|
case 2:
|
|
instrumentName = "snare";
|
|
break;
|
|
case 3:
|
|
instrumentName = "hat";
|
|
break;
|
|
case 4:
|
|
instrumentName = "bass";
|
|
break;
|
|
}
|
|
|
|
float f = (float) Math.pow(2.0D, (note - 12.0D) / 12.0D);
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note." + instrumentName), net.minecraft.server.SoundCategory.MUSIC, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f));
|
|
}
|
|
|
|
@Override
|
|
public void playNote(Location loc, Instrument instrument, Note note) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
String instrumentName = null;
|
|
switch (instrument.ordinal()) {
|
|
case 0:
|
|
instrumentName = "harp";
|
|
break;
|
|
case 1:
|
|
instrumentName = "basedrum";
|
|
break;
|
|
case 2:
|
|
instrumentName = "snare";
|
|
break;
|
|
case 3:
|
|
instrumentName = "hat";
|
|
break;
|
|
case 4:
|
|
instrumentName = "bass";
|
|
break;
|
|
}
|
|
float f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D);
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect("block.note." + instrumentName), net.minecraft.server.SoundCategory.MUSIC, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f));
|
|
}
|
|
|
|
@Override
|
|
public void playSound(Location loc, Sound sound, float volume, float pitch) {
|
|
playSound(loc, sound, org.bukkit.SoundCategory.MASTER, volume, pitch);
|
|
}
|
|
|
|
@Override
|
|
public void playSound(Location loc, String sound, float volume, float pitch) {
|
|
playSound(loc, sound, org.bukkit.SoundCategory.MASTER, volume, pitch);
|
|
}
|
|
|
|
@Override
|
|
public void playSound(Location loc, Sound sound, org.bukkit.SoundCategory category, float volume, float pitch) {
|
|
if (loc == null || sound == null || category == null || getHandle().playerConnection == null) return;
|
|
|
|
PacketPlayOutNamedSoundEffect packet = new PacketPlayOutNamedSoundEffect(CraftSound.getSoundEffect(CraftSound.getSound(sound)), net.minecraft.server.SoundCategory.valueOf(category.name()), loc.getX(), loc.getY(), loc.getZ(), volume, pitch);
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
|
|
@Override
|
|
public void playSound(Location loc, String sound, org.bukkit.SoundCategory category, float volume, float pitch) {
|
|
if (loc == null || sound == null || category == null || getHandle().playerConnection == null) return;
|
|
|
|
PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(sound, net.minecraft.server.SoundCategory.valueOf(category.name()), loc.getX(), loc.getY(), loc.getZ(), volume, pitch);
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
|
|
@Override
|
|
public void stopSound(Sound sound) {
|
|
stopSound(sound, null);
|
|
}
|
|
|
|
@Override
|
|
public void stopSound(String sound) {
|
|
stopSound(sound, null);
|
|
}
|
|
|
|
@Override
|
|
public void stopSound(Sound sound, org.bukkit.SoundCategory category) {
|
|
stopSound(CraftSound.getSound(sound), category);
|
|
}
|
|
|
|
@Override
|
|
public void stopSound(String sound, org.bukkit.SoundCategory category) {
|
|
if (getHandle().playerConnection == null) return;
|
|
PacketDataSerializer packetdataserializer = new PacketDataSerializer(Unpooled.buffer());
|
|
|
|
packetdataserializer.a(category == null ? "" : net.minecraft.server.SoundCategory.valueOf(category.name()).a());
|
|
packetdataserializer.a(sound);
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutCustomPayload("MC|StopSound", packetdataserializer));
|
|
}
|
|
|
|
@Override
|
|
public void playEffect(Location loc, Effect effect, int data) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
int packetData = effect.getId();
|
|
PacketPlayOutWorldEvent packet = new PacketPlayOutWorldEvent(packetData, new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), data, false);
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
|
|
@Override
|
|
public <T> void playEffect(Location loc, Effect effect, T data) {
|
|
if (data != null) {
|
|
Validate.isTrue(effect.getData() != null && effect.getData().isAssignableFrom(data.getClass()), "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().playerConnection == null) return;
|
|
|
|
PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(((CraftWorld) loc.getWorld()).getHandle(), new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
|
|
|
packet.block = CraftMagicNumbers.getBlock(material).fromLegacyData(data);
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
|
|
@Override
|
|
public void sendSignChange(Location loc, String[] lines) {
|
|
if (getHandle().playerConnection == 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");
|
|
}
|
|
|
|
IChatBaseComponent[] components = CraftSign.sanitizeLines(lines);
|
|
TileEntitySign sign = new TileEntitySign();
|
|
sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
|
System.arraycopy(components, 0, sign.lines, 0, sign.lines.length);
|
|
|
|
getHandle().playerConnection.sendPacket(sign.getUpdatePacket());
|
|
}
|
|
|
|
@Override
|
|
public boolean sendChunkChange(Location loc, int sx, int sy, int sz, byte[] data) {
|
|
if (getHandle().playerConnection == 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().playerConnection == null) return;
|
|
|
|
RenderData data = ((CraftMapView) map).render(this);
|
|
Collection<MapIcon> icons = new ArrayList<MapIcon>();
|
|
for (MapCursor cursor : data.cursors) {
|
|
if (cursor.isVisible()) {
|
|
icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection()));
|
|
}
|
|
}
|
|
|
|
PacketPlayOutMap packet = new PacketPlayOutMap(map.getId(), map.getScale().getValue(), true, icons, data.buffer, 0, 0, 128, 128);
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
|
|
@Override
|
|
public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) {
|
|
EntityPlayer entity = getHandle();
|
|
|
|
if (getHealth() == 0 || entity.dead) {
|
|
return false;
|
|
}
|
|
|
|
if (entity.playerConnection == null) {
|
|
return false;
|
|
}
|
|
|
|
if (entity.isVehicle()) {
|
|
return false;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// If this player is riding another entity, we must dismount before teleporting.
|
|
entity.stopRiding();
|
|
|
|
// 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.
|
|
WorldServer fromWorld = ((CraftWorld) from.getWorld()).getHandle();
|
|
WorldServer toWorld = ((CraftWorld) to.getWorld()).getHandle();
|
|
|
|
// Close any foreign inventory
|
|
if (getHandle().activeContainer != getHandle().defaultContainer) {
|
|
getHandle().closeInventory();
|
|
}
|
|
|
|
// Check if the fromWorld and toWorld are the same.
|
|
if (fromWorld == toWorld) {
|
|
entity.playerConnection.teleport(to);
|
|
} else {
|
|
server.getHandle().moveToWorld(entity, toWorld.dimension, true, to, true);
|
|
}
|
|
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().playerFileData.load(getHandle());
|
|
}
|
|
|
|
@Override
|
|
public void saveData() {
|
|
server.getHandle().playerFileData.save(getHandle());
|
|
}
|
|
|
|
@Deprecated
|
|
@Override
|
|
public void updateInventory() {
|
|
getHandle().updateInventory(getHandle().activeContainer);
|
|
}
|
|
|
|
@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) {
|
|
throw new UnsupportedOperationException("Not supported in this Minecraft version.");
|
|
}
|
|
|
|
@Override
|
|
public void removeAchievement(Achievement achievement) {
|
|
throw new UnsupportedOperationException("Not supported in this Minecraft version.");
|
|
}
|
|
|
|
@Override
|
|
public boolean hasAchievement(Achievement achievement) {
|
|
throw new UnsupportedOperationException("Not supported in this Minecraft version.");
|
|
}
|
|
|
|
@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().getStatisticManager().getStatisticValue(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.server.Statistic nmsStatistic = CraftStatistic.getNMSStatistic(statistic);
|
|
getHandle().getStatisticManager().setStatistic(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.server.Statistic nmsStatistic = CraftStatistic.getMaterialStatistic(statistic, material);
|
|
Validate.notNull(nmsStatistic, "The supplied Material does not have a corresponding statistic");
|
|
return getHandle().getStatisticManager().getStatisticValue(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.server.Statistic nmsStatistic = CraftStatistic.getMaterialStatistic(statistic, material);
|
|
Validate.notNull(nmsStatistic, "The supplied Material does not have a corresponding statistic");
|
|
getHandle().getStatisticManager().setStatistic(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.server.Statistic nmsStatistic = CraftStatistic.getEntityStatistic(statistic, entityType);
|
|
Validate.notNull(nmsStatistic, "The supplied EntityType does not have a corresponding statistic");
|
|
return getHandle().getStatisticManager().getStatisticValue(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.server.Statistic nmsStatistic = CraftStatistic.getEntityStatistic(statistic, entityType);
|
|
Validate.notNull(nmsStatistic, "The supplied EntityType does not have a corresponding statistic");
|
|
getHandle().getStatisticManager().setStatistic(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 boolean isWhitelisted() {
|
|
return server.getHandle().getWhitelist().isWhitelisted(getProfile());
|
|
}
|
|
|
|
@Override
|
|
public void setWhitelisted(boolean value) {
|
|
if (value) {
|
|
server.getHandle().addWhitelist(getProfile());
|
|
} else {
|
|
server.getHandle().removeWhitelist(getProfile());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setGameMode(GameMode mode) {
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
if (mode == null) {
|
|
throw new IllegalArgumentException("Mode cannot be null");
|
|
}
|
|
|
|
getHandle().a(EnumGamemode.getById(mode.getValue()));
|
|
}
|
|
|
|
@Override
|
|
public GameMode getGameMode() {
|
|
return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId());
|
|
}
|
|
|
|
@Override
|
|
public void giveExp(int exp) {
|
|
getHandle().giveExp(exp);
|
|
}
|
|
|
|
@Override
|
|
public void giveExpLevels(int levels) {
|
|
getHandle().levelDown(levels);
|
|
}
|
|
|
|
@Override
|
|
public float getExp() {
|
|
return getHandle().exp;
|
|
}
|
|
|
|
@Override
|
|
public void setExp(float exp) {
|
|
Preconditions.checkArgument(exp >= 0.0 && exp <= 1.0, "Experience progress must be between 0.0 and 1.0 (%s)", exp);
|
|
getHandle().exp = exp;
|
|
getHandle().lastSentExp = -1;
|
|
}
|
|
|
|
@Override
|
|
public int getLevel() {
|
|
return getHandle().expLevel;
|
|
}
|
|
|
|
@Override
|
|
public void setLevel(int level) {
|
|
getHandle().expLevel = level;
|
|
getHandle().lastSentExp = -1;
|
|
}
|
|
|
|
@Override
|
|
public int getTotalExperience() {
|
|
return getHandle().expTotal;
|
|
}
|
|
|
|
@Override
|
|
public void setTotalExperience(int exp) {
|
|
getHandle().expTotal = exp;
|
|
}
|
|
|
|
@Override
|
|
public float getExhaustion() {
|
|
return getHandle().getFoodData().exhaustionLevel;
|
|
}
|
|
|
|
@Override
|
|
public void setExhaustion(float value) {
|
|
getHandle().getFoodData().exhaustionLevel = value;
|
|
}
|
|
|
|
@Override
|
|
public float getSaturation() {
|
|
return getHandle().getFoodData().saturationLevel;
|
|
}
|
|
|
|
@Override
|
|
public void setSaturation(float value) {
|
|
getHandle().getFoodData().saturationLevel = value;
|
|
}
|
|
|
|
@Override
|
|
public int getFoodLevel() {
|
|
return getHandle().getFoodData().foodLevel;
|
|
}
|
|
|
|
@Override
|
|
public void setFoodLevel(int value) {
|
|
getHandle().getFoodData().foodLevel = value;
|
|
}
|
|
|
|
@Override
|
|
public Location getBedSpawnLocation() {
|
|
World world = getServer().getWorld(getHandle().spawnWorld);
|
|
BlockPosition bed = getHandle().getBed();
|
|
|
|
if (world != null && bed != null) {
|
|
bed = EntityHuman.getBed(((CraftWorld) world).getHandle(), bed, getHandle().isRespawnForced());
|
|
if (bed != null) {
|
|
return new Location(world, bed.getX(), bed.getY(), bed.getZ());
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void setBedSpawnLocation(Location location) {
|
|
setBedSpawnLocation(location, false);
|
|
}
|
|
|
|
@Override
|
|
public void setBedSpawnLocation(Location location, boolean override) {
|
|
if (location == null) {
|
|
getHandle().setRespawnPosition(null, override);
|
|
} else {
|
|
getHandle().setRespawnPosition(new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()), override);
|
|
getHandle().spawnWorld = location.getWorld().getName();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void hidePlayer(Player player) {
|
|
Validate.notNull(player, "hidden player cannot be null");
|
|
if (getHandle().playerConnection == 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
|
|
EntityTracker tracker = ((WorldServer) entity.world).tracker;
|
|
EntityPlayer other = ((CraftPlayer) player).getHandle();
|
|
EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(other.getId());
|
|
if (entry != null) {
|
|
entry.clear(getHandle());
|
|
}
|
|
|
|
// Remove the hidden player from this player user list, if they're on it
|
|
if (other.sentListPacket) {
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, other));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void showPlayer(Player player) {
|
|
Validate.notNull(player, "shown player cannot be null");
|
|
if (getHandle().playerConnection == null) return;
|
|
if (equals(player)) return;
|
|
if (!hiddenPlayers.contains(player.getUniqueId())) return;
|
|
hiddenPlayers.remove(player.getUniqueId());
|
|
|
|
EntityTracker tracker = ((WorldServer) entity.world).tracker;
|
|
EntityPlayer other = ((CraftPlayer) player).getHandle();
|
|
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other));
|
|
|
|
EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(other.getId());
|
|
if (entry != null && !entry.trackedPlayers.contains(getHandle())) {
|
|
entry.updatePlayer(getHandle());
|
|
}
|
|
}
|
|
|
|
public void removeDisconnectingPlayer(Player player) {
|
|
hiddenPlayers.remove(player.getUniqueId());
|
|
}
|
|
|
|
@Override
|
|
public boolean canSee(Player player) {
|
|
return !hiddenPlayers.contains(player.getUniqueId());
|
|
}
|
|
|
|
@Override
|
|
public Map<String, Object> serialize() {
|
|
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
|
|
result.put("name", getName());
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public Player getPlayer() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public EntityPlayer getHandle() {
|
|
return (EntityPlayer) entity;
|
|
}
|
|
|
|
public void setHandle(final EntityPlayer 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.getUniqueId() != null ? this.getUniqueId().hashCode() : 0);
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
@Override
|
|
public long getFirstPlayed() {
|
|
return firstPlayed;
|
|
}
|
|
|
|
@Override
|
|
public long getLastPlayed() {
|
|
return lastPlayed;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasPlayedBefore() {
|
|
return hasPlayedBefore;
|
|
}
|
|
|
|
public void setFirstPlayed(long firstPlayed) {
|
|
this.firstPlayed = firstPlayed;
|
|
}
|
|
|
|
public void readExtraData(NBTTagCompound nbttagcompound) {
|
|
hasPlayedBefore = true;
|
|
if (nbttagcompound.hasKey("bukkit")) {
|
|
NBTTagCompound data = nbttagcompound.getCompound("bukkit");
|
|
|
|
if (data.hasKey("firstPlayed")) {
|
|
firstPlayed = data.getLong("firstPlayed");
|
|
lastPlayed = data.getLong("lastPlayed");
|
|
}
|
|
|
|
if (data.hasKey("newExp")) {
|
|
EntityPlayer handle = getHandle();
|
|
handle.newExp = data.getInt("newExp");
|
|
handle.newTotalExp = data.getInt("newTotalExp");
|
|
handle.newLevel = data.getInt("newLevel");
|
|
handle.expToDrop = data.getInt("expToDrop");
|
|
handle.keepLevel = data.getBoolean("keepLevel");
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setExtraData(NBTTagCompound nbttagcompound) {
|
|
if (!nbttagcompound.hasKey("bukkit")) {
|
|
nbttagcompound.set("bukkit", new NBTTagCompound());
|
|
}
|
|
|
|
NBTTagCompound data = nbttagcompound.getCompound("bukkit");
|
|
EntityPlayer handle = getHandle();
|
|
data.setInt("newExp", handle.newExp);
|
|
data.setInt("newTotalExp", handle.newTotalExp);
|
|
data.setInt("newLevel", handle.newLevel);
|
|
data.setInt("expToDrop", handle.expToDrop);
|
|
data.setBoolean("keepLevel", handle.keepLevel);
|
|
data.setLong("firstPlayed", getFirstPlayed());
|
|
data.setLong("lastPlayed", System.currentTimeMillis());
|
|
data.setString("lastKnownName", handle.getName());
|
|
}
|
|
|
|
@Override
|
|
public boolean beginConversation(Conversation conversation) {
|
|
return conversationTracker.beginConversation(conversation);
|
|
}
|
|
|
|
@Override
|
|
public void abandonConversation(Conversation conversation) {
|
|
conversationTracker.abandonConversation(conversation, new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller()));
|
|
}
|
|
|
|
@Override
|
|
public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) {
|
|
conversationTracker.abandonConversation(conversation, details);
|
|
}
|
|
|
|
@Override
|
|
public void acceptConversationInput(String input) {
|
|
conversationTracker.acceptConversationInput(input);
|
|
}
|
|
|
|
@Override
|
|
public boolean isConversing() {
|
|
return conversationTracker.isConversing();
|
|
}
|
|
|
|
@Override
|
|
public void sendPluginMessage(Plugin source, String channel, byte[] message) {
|
|
StandardMessenger.validatePluginMessage(server.getMessenger(), source, channel, message);
|
|
if (getHandle().playerConnection == null) return;
|
|
|
|
if (channels.contains(channel)) {
|
|
PacketPlayOutCustomPayload packet = new PacketPlayOutCustomPayload(channel, new PacketDataSerializer(Unpooled.wrappedBuffer(message)));
|
|
getHandle().playerConnection.sendPacket(packet);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setTexturePack(String url) {
|
|
setResourcePack(url);
|
|
}
|
|
|
|
@Override
|
|
public void setResourcePack(String url) {
|
|
Validate.notNull(url, "Resource pack URL cannot be null");
|
|
|
|
getHandle().setResourcePack(url, "null");
|
|
}
|
|
|
|
@Override
|
|
public void setResourcePack(String url, byte[] hash) {
|
|
Validate.notNull(url, "Resource pack URL cannot be null");
|
|
Validate.notNull(hash, "Resource pack hash cannot be null");
|
|
Validate.isTrue(hash.length == 20, "Resource pack hash should be 20 bytes long but was " + hash.length);
|
|
|
|
getHandle().setResourcePack(url, BaseEncoding.base16().lowerCase().encode(hash));
|
|
}
|
|
|
|
public void addChannel(String channel) {
|
|
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));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getListeningPluginChannels() {
|
|
return ImmutableSet.copyOf(channels);
|
|
}
|
|
|
|
public void sendSupportedChannels() {
|
|
if (getHandle().playerConnection == 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().playerConnection.sendPacket(new PacketPlayOutCustomPayload("REGISTER", new PacketDataSerializer(Unpooled.wrappedBuffer(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) {
|
|
Container container = getHandle().activeContainer;
|
|
if (container.getBukkitView().getType() != prop.getType()) {
|
|
return false;
|
|
}
|
|
getHandle().setContainerData(container, prop.getId(), value);
|
|
return true;
|
|
}
|
|
|
|
public void disconnect(String reason) {
|
|
conversationTracker.abandonAllConversations();
|
|
perm.clearPermissions();
|
|
}
|
|
|
|
@Override
|
|
public boolean isFlying() {
|
|
return getHandle().abilities.isFlying;
|
|
}
|
|
|
|
@Override
|
|
public void setFlying(boolean value) {
|
|
if (!getAllowFlight() && value) {
|
|
throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false");
|
|
}
|
|
|
|
getHandle().abilities.isFlying = value;
|
|
getHandle().updateAbilities();
|
|
}
|
|
|
|
@Override
|
|
public boolean getAllowFlight() {
|
|
return getHandle().abilities.canFly;
|
|
}
|
|
|
|
@Override
|
|
public void setAllowFlight(boolean value) {
|
|
if (isFlying() && !value) {
|
|
getHandle().abilities.isFlying = false;
|
|
}
|
|
|
|
getHandle().abilities.canFly = value;
|
|
getHandle().updateAbilities();
|
|
}
|
|
|
|
@Override
|
|
public int getNoDamageTicks() {
|
|
if (getHandle().invulnerableTicks > 0) {
|
|
return Math.max(getHandle().invulnerableTicks, getHandle().noDamageTicks);
|
|
} else {
|
|
return getHandle().noDamageTicks;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setFlySpeed(float value) {
|
|
validateSpeed(value);
|
|
EntityPlayer player = getHandle();
|
|
player.abilities.flySpeed = value / 2f;
|
|
player.updateAbilities();
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setWalkSpeed(float value) {
|
|
validateSpeed(value);
|
|
EntityPlayer player = getHandle();
|
|
player.abilities.walkSpeed = value / 2f;
|
|
player.updateAbilities();
|
|
}
|
|
|
|
@Override
|
|
public float getFlySpeed() {
|
|
return getHandle().abilities.flySpeed * 2f;
|
|
}
|
|
|
|
@Override
|
|
public float getWalkSpeed() {
|
|
return getHandle().abilities.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().triggerHealthUpdate();
|
|
}
|
|
|
|
@Override
|
|
public void resetMaxHealth() {
|
|
super.resetMaxHealth();
|
|
getHandle().triggerHealthUpdate();
|
|
}
|
|
|
|
@Override
|
|
public CraftScoreboard getScoreboard() {
|
|
return this.server.getScoreboardManager().getPlayerBoard(this);
|
|
}
|
|
|
|
@Override
|
|
public void setScoreboard(Scoreboard scoreboard) {
|
|
Validate.notNull(scoreboard, "Scoreboard cannot be null");
|
|
PlayerConnection playerConnection = getHandle().playerConnection;
|
|
if (playerConnection == null) {
|
|
throw new IllegalStateException("Cannot set scoreboard yet");
|
|
}
|
|
if (playerConnection.isDisconnected()) {
|
|
throw new IllegalStateException("Cannot set scoreboard for invalid CraftPlayer");
|
|
}
|
|
|
|
this.server.getScoreboardManager().setPlayerBoard(this, scoreboard);
|
|
}
|
|
|
|
@Override
|
|
public void setHealthScale(double value) {
|
|
Validate.isTrue((float) value > 0F, "Must be greater than 0");
|
|
healthScale = value;
|
|
scaledHealth = true;
|
|
updateScaledHealth();
|
|
}
|
|
|
|
@Override
|
|
public double getHealthScale() {
|
|
return healthScale;
|
|
}
|
|
|
|
@Override
|
|
public void setHealthScaled(boolean scale) {
|
|
if (scaledHealth != (scaledHealth = scale)) {
|
|
updateScaledHealth();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
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() {
|
|
AttributeMapServer attributemapserver = (AttributeMapServer) getHandle().getAttributeMap();
|
|
Collection set = attributemapserver.c(); // PAIL: Rename
|
|
|
|
injectScaledMaxHealth(set, true);
|
|
|
|
getHandle().getDataWatcher().set(EntityLiving.HEALTH, (float) getScaledHealth());
|
|
sendHealthUpdate();
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(getHandle().getId(), set));
|
|
|
|
getHandle().maxHealthCache = getMaxHealth();
|
|
}
|
|
|
|
public void sendHealthUpdate() {
|
|
getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()));
|
|
}
|
|
|
|
public void injectScaledMaxHealth(Collection collection, boolean force) {
|
|
if (!scaledHealth && !force) {
|
|
return;
|
|
}
|
|
for (Object genericInstance : collection) {
|
|
IAttribute attribute = ((AttributeInstance) genericInstance).getAttribute();
|
|
if (attribute.getName().equals("generic.maxHealth")) {
|
|
collection.remove(genericInstance);
|
|
break;
|
|
}
|
|
}
|
|
collection.add(new AttributeModifiable(getHandle().getAttributeMap(), (new AttributeRanged(null, "generic.maxHealth", scaledHealth ? healthScale : getMaxHealth(), 0.0D, Float.MAX_VALUE)).a("Max Health").a(true)));
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.entity.Entity getSpectatorTarget() {
|
|
Entity followed = getHandle().getSpecatorTarget();
|
|
return followed == getHandle() ? null : followed.getBukkitEntity();
|
|
}
|
|
|
|
@Override
|
|
public void setSpectatorTarget(org.bukkit.entity.Entity entity) {
|
|
Preconditions.checkArgument(getGameMode() == GameMode.SPECTATOR, "Player must be in spectator mode");
|
|
getHandle().setSpectatorTarget((entity == null) ? null : ((CraftEntity) entity).getHandle());
|
|
}
|
|
|
|
@Override
|
|
public void sendTitle(String title, String subtitle) {
|
|
sendTitle(title, subtitle, 10, 70, 20);
|
|
}
|
|
|
|
@Override
|
|
public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
|
if (title != null) {
|
|
PacketPlayOutTitle packetTitle = new PacketPlayOutTitle(EnumTitleAction.TITLE, CraftChatMessage.fromString(title)[0]);
|
|
getHandle().playerConnection.sendPacket(packetTitle);
|
|
}
|
|
|
|
if (subtitle != null) {
|
|
PacketPlayOutTitle packetSubtitle = new PacketPlayOutTitle(EnumTitleAction.SUBTITLE, CraftChatMessage.fromString(subtitle)[0]);
|
|
getHandle().playerConnection.sendPacket(packetSubtitle);
|
|
}
|
|
|
|
PacketPlayOutTitle times = new PacketPlayOutTitle(fadeIn, stay, fadeOut);
|
|
getHandle().playerConnection.sendPacket(times);
|
|
}
|
|
|
|
@Override
|
|
public void resetTitle() {
|
|
PacketPlayOutTitle packetReset = new PacketPlayOutTitle(EnumTitleAction.RESET, null);
|
|
getHandle().playerConnection.sendPacket(packetReset);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, Location location, int count) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, double x, double y, double z, int count) {
|
|
spawnParticle(particle, x, y, z, count, null);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, Location location, int count, T data) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count, data);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, T data) {
|
|
spawnParticle(particle, x, y, z, count, 0, 0, 0, data);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count, offsetX, offsetY, offsetZ);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ) {
|
|
spawnParticle(particle, x, y, z, count, offsetX, offsetY, offsetZ, null);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, T data) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count, offsetX, offsetY, offsetZ, data);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, T data) {
|
|
spawnParticle(particle, x, y, z, count, offsetX, offsetY, offsetZ, 1, data);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count, offsetX, offsetY, offsetZ, extra);
|
|
}
|
|
|
|
@Override
|
|
public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra) {
|
|
spawnParticle(particle, x, y, z, count, offsetX, offsetY, offsetZ, extra, null);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra, T data) {
|
|
spawnParticle(particle, location.getX(), location.getY(), location.getZ(), count, offsetX, offsetY, offsetZ, extra, data);
|
|
}
|
|
|
|
@Override
|
|
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data) {
|
|
if (data != null && !particle.getDataType().isInstance(data)) {
|
|
throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass());
|
|
}
|
|
PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count, CraftParticle.toData(particle, data));
|
|
getHandle().playerConnection.sendPacket(packetplayoutworldparticles);
|
|
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.advancement.AdvancementProgress getAdvancementProgress(org.bukkit.advancement.Advancement advancement) {
|
|
Preconditions.checkArgument(advancement != null, "advancement");
|
|
|
|
CraftAdvancement craft = (CraftAdvancement) advancement;
|
|
AdvancementDataPlayer data = getHandle().getAdvancementData();
|
|
AdvancementProgress progress = data.getProgress(craft.getHandle());
|
|
|
|
return new CraftAdvancementProgress(craft, data, progress);
|
|
}
|
|
|
|
@Override
|
|
public String getLocale() {
|
|
return getHandle().locale;
|
|
}
|
|
}
|