T00thpick1 1192f2a53a Add API to control scaled health. Adds BUKKIT-4590
This commit implements the ability to set the scale of hearts that the
client renders.  When the Packet44UpdateAttributes packet is sent, the
max health attribute is replaced with a scaled version, to preserve the
scaled health illusion clientside.

In order to accurately display the scaled health for players, a true
health is stored within CraftPlayer, and the datawatcher now stores the
scaled health. The getHealth() method for players still returns their
true health.

Changed setHealth() within EntityLiving to appropriately handle health
for instances of EntityPlayer. Inlined a call to
setHealth(getMaxHealth()) within the EntityLiving constructor to work
around CraftEntity instantiation.

Additionally fixes the health values sent when eating food within
FoodMetaData and ItemFood, which previously sent the unscaled health;
this commit alters them to send the properly scaled health.

Additionally fixes BUKKIT-4535, BUKKIT-4536, and BUKKIT-4127
2013-07-23 21:52:17 -05:00

957 lines
37 KiB
Java

package net.minecraft.server;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
// CraftBukkit start
import org.bukkit.Bukkit;
import org.bukkit.WeatherType;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
// CraftBukkit end
public class EntityPlayer extends EntityHuman implements ICrafting {
private String locale = "en_US";
public PlayerConnection playerConnection;
public MinecraftServer server;
public PlayerInteractManager playerInteractManager;
public double d;
public double e;
public final List chunkCoordIntPairQueue = new LinkedList();
public final List removeQueue = new LinkedList();
private float bO = Float.MIN_VALUE;
private float bP = -1.0E8F;
private int bQ = -99999999;
private boolean bR = true;
public int lastSentExp = -99999999; // CraftBukkit - private -> public
public int invulnerableTicks = 60; // CraftBukkit - private -> public
private int bU;
private int bV;
private boolean bW = true;
private int containerCounter;
public boolean h;
public int ping;
public boolean viewingCredits;
// CraftBukkit start
public String displayName;
public String listName;
public org.bukkit.Location compassTarget;
public int newExp = 0;
public int newLevel = 0;
public int newTotalExp = 0;
public boolean keepLevel = false;
public double maxHealthCache;
// CraftBukkit end
public EntityPlayer(MinecraftServer minecraftserver, World world, String s, PlayerInteractManager playerinteractmanager) {
super(world, s);
playerinteractmanager.player = this;
this.playerInteractManager = playerinteractmanager;
this.bU = minecraftserver.getPlayerList().o();
ChunkCoordinates chunkcoordinates = world.getSpawn();
int i = chunkcoordinates.x;
int j = chunkcoordinates.z;
int k = chunkcoordinates.y;
if (!world.worldProvider.g && world.getWorldData().getGameType() != EnumGamemode.ADVENTURE) {
int l = Math.max(5, minecraftserver.getSpawnProtection() - 6);
i += this.random.nextInt(l * 2) - l;
j += this.random.nextInt(l * 2) - l;
k = world.i(i, j);
}
this.server = minecraftserver;
this.Y = 0.0F;
this.height = 0.0F;
this.setPositionRotation((double) i + 0.5D, (double) k, (double) j + 0.5D, 0.0F, 0.0F);
while (!world.getCubes(this, this.boundingBox).isEmpty()) {
this.setPosition(this.locX, this.locY + 1.0D, this.locZ);
}
// CraftBukkit start
this.displayName = this.name;
this.listName = this.name;
// this.canPickUpLoot = true; TODO
this.maxHealthCache = this.getMaxHealth();
// CraftBukkit end
}
public void a(NBTTagCompound nbttagcompound) {
super.a(nbttagcompound);
if (nbttagcompound.hasKey("playerGameType")) {
if (MinecraftServer.getServer().getForceGamemode()) {
this.playerInteractManager.setGameMode(MinecraftServer.getServer().getGamemode());
} else {
this.playerInteractManager.setGameMode(EnumGamemode.a(nbttagcompound.getInt("playerGameType")));
}
}
this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit
}
public void b(NBTTagCompound nbttagcompound) {
super.b(nbttagcompound);
nbttagcompound.setInt("playerGameType", this.playerInteractManager.getGameMode().a());
this.getBukkitEntity().setExtraData(nbttagcompound); // CraftBukkit
}
// CraftBukkit start - World fallback code, either respawn location or global spawn
public void spawnIn(World world) {
super.spawnIn(world);
if (world == null) {
this.dead = false;
ChunkCoordinates position = null;
if (this.spawnWorld != null && !this.spawnWorld.equals("")) {
CraftWorld cworld = (CraftWorld) Bukkit.getServer().getWorld(this.spawnWorld);
if (cworld != null && this.getBed() != null) {
world = cworld.getHandle();
position = EntityHuman.getBed(cworld.getHandle(), this.getBed(), false);
}
}
if (world == null || position == null) {
world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle();
position = world.getSpawn();
}
this.world = world;
this.setPosition(position.x + 0.5, position.y, position.z + 0.5);
}
this.dimension = ((WorldServer) this.world).dimension;
this.playerInteractManager.a((WorldServer) world);
}
// CraftBukkit end
public void levelDown(int i) {
super.levelDown(i);
this.lastSentExp = -1;
}
public void syncInventory() {
this.activeContainer.addSlotListener(this);
}
protected void d_() {
this.height = 0.0F;
}
public float getHeadHeight() {
return 1.62F;
}
public void l_() {
this.playerInteractManager.a();
--this.invulnerableTicks;
this.activeContainer.b();
if (!this.world.isStatic && !this.activeContainer.a((EntityHuman) this)) {
this.closeInventory();
this.activeContainer = this.defaultContainer;
}
// CraftBukkit start - Check inventory status every tick
if (!this.activeContainer.a(this)) { // Should be stillValid
this.closeInventory();
this.activeContainer = this.defaultContainer;
}
// CraftBukkit end
while (!this.removeQueue.isEmpty()) {
int i = Math.min(this.removeQueue.size(), 127);
int[] aint = new int[i];
Iterator iterator = this.removeQueue.iterator();
int j = 0;
while (iterator.hasNext() && j < i) {
aint[j++] = ((Integer) iterator.next()).intValue();
iterator.remove();
}
this.playerConnection.sendPacket(new Packet29DestroyEntity(aint));
}
if (!this.chunkCoordIntPairQueue.isEmpty()) {
ArrayList arraylist = new ArrayList();
Iterator iterator1 = this.chunkCoordIntPairQueue.iterator();
ArrayList arraylist1 = new ArrayList();
while (iterator1.hasNext() && arraylist.size() < 5) {
ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator1.next();
iterator1.remove();
if (chunkcoordintpair != null && this.world.isLoaded(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4)) {
// CraftBukkit start - Get tile entities directly from the chunk instead of the world
Chunk chunk = this.world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z);
arraylist.add(chunk);
arraylist1.addAll(chunk.tileEntities.values());
// CraftBukkit end
}
}
if (!arraylist.isEmpty()) {
this.playerConnection.sendPacket(new Packet56MapChunkBulk(arraylist));
Iterator iterator2 = arraylist1.iterator();
while (iterator2.hasNext()) {
TileEntity tileentity = (TileEntity) iterator2.next();
this.b(tileentity);
}
iterator2 = arraylist.iterator();
while (iterator2.hasNext()) {
Chunk chunk = (Chunk) iterator2.next();
this.p().getTracker().a(this, chunk);
}
}
}
}
public void h() {
try {
super.l_();
for (int i = 0; i < this.inventory.getSize(); ++i) {
ItemStack itemstack = this.inventory.getItem(i);
if (itemstack != null && Item.byId[itemstack.id].f() && this.playerConnection.lowPriorityCount() <= 5) {
Packet packet = ((ItemWorldMapBase) Item.byId[itemstack.id]).c(itemstack, this.world, this);
if (packet != null) {
this.playerConnection.sendPacket(packet);
}
}
}
if (this.getHealth() != this.bP || this.bQ != this.foodData.a() || this.foodData.e() == 0.0F != this.bR) {
// CraftBukkit - Optionally scale health
this.playerConnection.sendPacket(new Packet8UpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.a(), this.foodData.e()));
this.bP = this.getHealth();
this.bQ = this.foodData.a();
this.bR = this.foodData.e() == 0.0F;
}
if (this.getHealth() + this.bm() != this.bO) {
this.bO = this.getHealth() + this.bm();
// CraftBukkit - Update ALL the scores!
this.world.getServer().getScoreboardManager().updateAllScoresForList(IScoreboardCriteria.f, this.getLocalizedName(), com.google.common.collect.ImmutableList.of(this));
}
// CraftBukkit start - Force max health updates
if (this.maxHealthCache != this.getMaxHealth()) {
this.getBukkitEntity().updateScaledHealth();
}
// CraftBukkit end
if (this.expTotal != this.lastSentExp) {
this.lastSentExp = this.expTotal;
this.playerConnection.sendPacket(new Packet43SetExperience(this.exp, this.expTotal, this.expLevel));
}
// CraftBukkit start
if (this.oldLevel == -1) {
this.oldLevel = this.expLevel;
}
if (this.oldLevel != this.expLevel) {
CraftEventFactory.callPlayerLevelChangeEvent(this.world.getServer().getPlayer((EntityPlayer) this), this.oldLevel, this.expLevel);
this.oldLevel = this.expLevel;
}
// CraftBukkit end
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Ticking player");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Player being ticked");
this.a(crashreportsystemdetails);
throw new ReportedException(crashreport);
}
}
public void die(DamageSource damagesource) {
// CraftBukkit start
if (this.dead) {
return;
}
java.util.List<org.bukkit.inventory.ItemStack> loot = new java.util.ArrayList<org.bukkit.inventory.ItemStack>();
boolean keepInventory = this.world.getGameRules().getBoolean("keepInventory");
if (!keepInventory) {
for (int i = 0; i < this.inventory.items.length; ++i) {
if (this.inventory.items[i] != null) {
loot.add(CraftItemStack.asCraftMirror(this.inventory.items[i]));
}
}
for (int i = 0; i < this.inventory.armor.length; ++i) {
if (this.inventory.armor[i] != null) {
loot.add(CraftItemStack.asCraftMirror(this.inventory.armor[i]));
}
}
}
ChatMessage chatmessage = this.aQ().b();
String deathmessage = chatmessage.toString();
org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage);
String deathMessage = event.getDeathMessage();
if (deathMessage != null && deathMessage.length() > 0) {
if (deathMessage.equals(chatmessage.toString())) {
this.server.getPlayerList().sendMessage(chatmessage);
} else {
this.server.getPlayerList().sendMessage(ChatMessage.d(event.getDeathMessage()));
}
}
// CraftBukkit - we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
if (!keepInventory) {
for (int i = 0; i < this.inventory.items.length; ++i) {
this.inventory.items[i] = null;
}
for (int i = 0; i < this.inventory.armor.length; ++i) {
this.inventory.armor[i] = null;
}
}
this.closeInventory();
// CraftBukkit end
// CraftBukkit - Get our scores instead
Collection<ScoreboardScore> collection = this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.c, this.getLocalizedName(), new java.util.ArrayList<ScoreboardScore>());
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
ScoreboardScore scoreboardscore = (ScoreboardScore) iterator.next(); // CraftBukkit - Use our scores instead
scoreboardscore.incrementScore();
}
EntityLiving entityliving = this.aR();
if (entityliving != null) {
entityliving.b(this, this.bb);
}
this.a(StatisticList.y, 1);
}
public boolean damageEntity(DamageSource damagesource, float f) {
if (this.isInvulnerable()) {
return false;
} else {
// CraftBukkit - this.server.getPvP() -> this.world.pvpMode
boolean flag = this.server.V() && this.world.pvpMode && "fall".equals(damagesource.translationIndex);
if (!flag && this.invulnerableTicks > 0 && damagesource != DamageSource.OUT_OF_WORLD) {
return false;
} else {
if (damagesource instanceof EntityDamageSource) {
Entity entity = damagesource.getEntity();
if (entity instanceof EntityHuman && !this.a((EntityHuman) entity)) {
return false;
}
if (entity instanceof EntityArrow) {
EntityArrow entityarrow = (EntityArrow) entity;
if (entityarrow.shooter instanceof EntityHuman && !this.a((EntityHuman) entityarrow.shooter)) {
return false;
}
}
}
return super.damageEntity(damagesource, f);
}
}
}
public boolean a(EntityHuman entityhuman) {
// CraftBukkit - this.server.getPvP() -> this.world.pvpMode
return !this.world.pvpMode ? false : super.a(entityhuman);
}
public void b(int i) {
if (this.dimension == 1 && i == 1) {
this.a((Statistic) AchievementList.C);
this.world.kill(this);
this.viewingCredits = true;
this.playerConnection.sendPacket(new Packet70Bed(4, 0));
} else {
if (this.dimension == 0 && i == 1) {
this.a((Statistic) AchievementList.B);
// CraftBukkit start - Rely on custom portal management
/*
ChunkCoordinates chunkcoordinates = this.server.getWorldServer(i).getDimensionSpawn();
if (chunkcoordinates != null) {
this.playerConnection.a((double) chunkcoordinates.x, (double) chunkcoordinates.y, (double) chunkcoordinates.z, 0.0F, 0.0F);
}
i = 1;
*/
// CraftBukkit end
} else {
this.a((Statistic) AchievementList.x);
}
// CraftBukkit start
TeleportCause cause = (this.dimension == 1 || i == 1) ? TeleportCause.END_PORTAL : TeleportCause.NETHER_PORTAL;
this.server.getPlayerList().changeDimension(this, i, cause);
// CraftBukkit end
this.lastSentExp = -1;
this.bP = -1.0F;
this.bQ = -1;
}
}
private void b(TileEntity tileentity) {
if (tileentity != null) {
Packet packet = tileentity.getUpdatePacket();
if (packet != null) {
this.playerConnection.sendPacket(packet);
}
}
}
public void receive(Entity entity, int i) {
super.receive(entity, i);
this.activeContainer.b();
}
public EnumBedResult a(int i, int j, int k) {
EnumBedResult enumbedresult = super.a(i, j, k);
if (enumbedresult == EnumBedResult.OK) {
Packet17EntityLocationAction packet17entitylocationaction = new Packet17EntityLocationAction(this, 0, i, j, k);
this.p().getTracker().a((Entity) this, (Packet) packet17entitylocationaction);
this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
this.playerConnection.sendPacket(packet17entitylocationaction);
}
return enumbedresult;
}
public void a(boolean flag, boolean flag1, boolean flag2) {
if (this.fauxSleeping && !this.sleeping) return; // CraftBukkit - Can't leave bed if not in one!
if (this.isSleeping()) {
this.p().getTracker().sendPacketToEntity(this, new Packet18ArmAnimation(this, 3));
}
super.a(flag, flag1, flag2);
if (this.playerConnection != null) {
this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
}
}
public void mount(Entity entity) {
// CraftBukkit start
this.setPassengerOf(entity);
}
public void setPassengerOf(Entity entity) {
// mount(null) doesn't really fly for overloaded methods,
// so this method is needed
Entity currentVehicle = this.vehicle;
super.setPassengerOf(entity);
// Check if the vehicle actually changed.
if (currentVehicle != this.vehicle) {
this.playerConnection.sendPacket(new Packet39AttachEntity(0, this, this.vehicle));
this.playerConnection.a(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
}
// CraftBukkit end
}
protected void a(double d0, boolean flag) {}
public void b(double d0, boolean flag) {
super.a(d0, flag);
}
public void a(TileEntity tileentity) {
if (tileentity instanceof TileEntitySign) {
((TileEntitySign) tileentity).a((EntityHuman) this);
this.playerConnection.sendPacket(new Packet133OpenTileEntity(0, tileentity.x, tileentity.y, tileentity.z));
}
}
public int nextContainerCounter() { // CraftBukkit - private void -> public int
this.containerCounter = this.containerCounter % 100 + 1;
return this.containerCounter; // CraftBukkit
}
public void startCrafting(int i, int j, int k) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerWorkbench(this.inventory, this.world, i, j, k));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 1, "Crafting", 9, true));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void startEnchanting(int i, int j, int k, String s) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerEnchantTable(this.inventory, this.world, i, j, k));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 4, s == null ? "" : s, 9, s != null));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openAnvil(int i, int j, int k) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerAnvil(this.inventory, this.world, i, j, k, this));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 8, "Repairing", 9, true));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openContainer(IInventory iinventory) {
if (this.activeContainer != this.defaultContainer) {
this.closeInventory();
}
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerChest(this.inventory, iinventory));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 0, iinventory.getName(), iinventory.getSize(), iinventory.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openHopper(TileEntityHopper tileentityhopper) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerHopper(this.inventory, tileentityhopper));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 9, tileentityhopper.getName(), tileentityhopper.getSize(), tileentityhopper.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openMinecartHopper(EntityMinecartHopper entityminecarthopper) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerHopper(this.inventory, entityminecarthopper));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 9, entityminecarthopper.getName(), entityminecarthopper.getSize(), entityminecarthopper.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openFurnace(TileEntityFurnace tileentityfurnace) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerFurnace(this.inventory, tileentityfurnace));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 2, tileentityfurnace.getName(), tileentityfurnace.getSize(), tileentityfurnace.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openDispenser(TileEntityDispenser tileentitydispenser) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerDispenser(this.inventory, tileentitydispenser));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, tileentitydispenser instanceof TileEntityDropper ? 10 : 3, tileentitydispenser.getName(), tileentitydispenser.getSize(), tileentitydispenser.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openBrewingStand(TileEntityBrewingStand tileentitybrewingstand) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerBrewingStand(this.inventory, tileentitybrewingstand));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 5, tileentitybrewingstand.getName(), tileentitybrewingstand.getSize(), tileentitybrewingstand.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openBeacon(TileEntityBeacon tileentitybeacon) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerBeacon(this.inventory, tileentitybeacon));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 7, tileentitybeacon.getName(), tileentitybeacon.getSize(), tileentitybeacon.c()));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void openTrade(IMerchant imerchant, String s) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerMerchant(this.inventory, imerchant, this.world));
if(container == null) return;
// CraftBukkit end
this.nextContainerCounter();
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
InventoryMerchant inventorymerchant = ((ContainerMerchant) this.activeContainer).getMerchantInventory();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 6, s == null ? "" : s, inventorymerchant.getSize(), s != null));
MerchantRecipeList merchantrecipelist = imerchant.getOffers(this);
if (merchantrecipelist != null) {
try {
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
dataoutputstream.writeInt(this.containerCounter);
merchantrecipelist.a(dataoutputstream);
this.playerConnection.sendPacket(new Packet250CustomPayload("MC|TrList", bytearrayoutputstream.toByteArray()));
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
}
public void openHorseInventory(EntityHorse entityhorse, IInventory iinventory) {
// CraftBukkit start - Inventory open hook
Container container = CraftEventFactory.callInventoryOpenEvent(this, new ContainerHorse(this.inventory, iinventory, entityhorse));
if(container == null) return;
// CraftBukkit end
if (this.activeContainer != this.defaultContainer) {
this.closeInventory();
}
this.nextContainerCounter();
this.playerConnection.sendPacket(new Packet100OpenWindow(this.containerCounter, 11, iinventory.getName(), iinventory.getSize(), iinventory.c(), entityhorse.id));
this.activeContainer = container; // CraftBukkit - Use container we passed to event
this.activeContainer.windowId = this.containerCounter;
this.activeContainer.addSlotListener(this);
}
public void a(Container container, int i, ItemStack itemstack) {
if (!(container.getSlot(i) instanceof SlotResult)) {
if (!this.h) {
this.playerConnection.sendPacket(new Packet103SetSlot(container.windowId, i, itemstack));
}
}
}
public void updateInventory(Container container) {
this.a(container, container.a());
}
public void a(Container container, List list) {
this.playerConnection.sendPacket(new Packet104WindowItems(container.windowId, list));
this.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.inventory.getCarried()));
// CraftBukkit start - Send a Set Slot to update the crafting result slot
if (java.util.EnumSet.of(InventoryType.CRAFTING,InventoryType.WORKBENCH).contains(container.getBukkitView().getType())) {
this.playerConnection.sendPacket(new Packet103SetSlot(container.windowId, 0, container.getSlot(0).getItem()));
}
// CraftBukkit end
}
public void setContainerData(Container container, int i, int j) {
this.playerConnection.sendPacket(new Packet105CraftProgressBar(container.windowId, i, j));
}
public void closeInventory() {
CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit
this.playerConnection.sendPacket(new Packet101CloseWindow(this.activeContainer.windowId));
this.k();
}
public void broadcastCarriedItem() {
if (!this.h) {
this.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.inventory.getCarried()));
}
}
public void k() {
this.activeContainer.b((EntityHuman) this);
this.activeContainer = this.defaultContainer;
}
public void a(float f, float f1, boolean flag, boolean flag1) {
if (this.vehicle != null) {
if (f >= -1.0F && f <= 1.0F) {
this.be = f;
}
if (f1 >= -1.0F && f1 <= 1.0F) {
this.bf = f1;
}
this.bd = flag;
this.setSneaking(flag1);
}
}
public void a(Statistic statistic, int i) {
if (statistic != null) {
if (!statistic.f) {
this.playerConnection.sendPacket(new Packet200Statistic(statistic.e, i));
}
}
}
public void l() {
if (this.passenger != null) {
this.passenger.mount(this);
}
if (this.sleeping) {
this.a(true, false, false);
}
}
public void triggerHealthUpdate() {
this.bP = -1.0E8F;
this.lastSentExp = -1; // CraftBukkit - Added to reset
}
public void a(String s) {
this.playerConnection.sendPacket(new Packet3Chat(ChatMessage.e(s)));
}
protected void n() {
this.playerConnection.sendPacket(new Packet38EntityStatus(this.id, (byte) 9));
super.n();
}
public void a(ItemStack itemstack, int i) {
super.a(itemstack, i);
if (itemstack != null && itemstack.getItem() != null && itemstack.getItem().c_(itemstack) == EnumAnimation.EAT) {
this.p().getTracker().sendPacketToEntity(this, new Packet18ArmAnimation(this, 5));
}
}
public void copyTo(EntityHuman entityhuman, boolean flag) {
super.copyTo(entityhuman, flag);
this.lastSentExp = -1;
this.bP = -1.0F;
this.bQ = -1;
this.removeQueue.addAll(((EntityPlayer) entityhuman).removeQueue);
}
protected void a(MobEffect mobeffect) {
super.a(mobeffect);
this.playerConnection.sendPacket(new Packet41MobEffect(this.id, mobeffect));
}
protected void a(MobEffect mobeffect, boolean flag) {
super.a(mobeffect, flag);
this.playerConnection.sendPacket(new Packet41MobEffect(this.id, mobeffect));
}
protected void b(MobEffect mobeffect) {
super.b(mobeffect);
this.playerConnection.sendPacket(new Packet42RemoveMobEffect(this.id, mobeffect));
}
public void enderTeleportTo(double d0, double d1, double d2) {
this.playerConnection.a(d0, d1, d2, this.yaw, this.pitch);
}
public void b(Entity entity) {
this.p().getTracker().sendPacketToEntity(this, new Packet18ArmAnimation(entity, 6));
}
public void c(Entity entity) {
this.p().getTracker().sendPacketToEntity(this, new Packet18ArmAnimation(entity, 7));
}
public void updateAbilities() {
if (this.playerConnection != null) {
this.playerConnection.sendPacket(new Packet202Abilities(this.abilities));
}
}
public WorldServer p() {
return (WorldServer) this.world;
}
public void a(EnumGamemode enumgamemode) {
this.playerInteractManager.setGameMode(enumgamemode);
this.playerConnection.sendPacket(new Packet70Bed(3, enumgamemode.a()));
}
public void sendMessage(ChatMessage chatmessage) {
this.playerConnection.sendPacket(new Packet3Chat(chatmessage));
}
public boolean a(int i, String s) {
return "seed".equals(s) && !this.server.V() ? true : (!"tell".equals(s) && !"help".equals(s) && !"me".equals(s) ? (this.server.getPlayerList().isOp(this.name) ? this.server.k() >= i : false) : true);
}
public String q() {
String s = this.playerConnection.networkManager.getSocketAddress().toString();
s = s.substring(s.indexOf("/") + 1);
s = s.substring(0, s.indexOf(":"));
return s;
}
public void a(Packet204LocaleAndViewDistance packet204localeandviewdistance) {
this.locale = packet204localeandviewdistance.d();
int i = 256 >> packet204localeandviewdistance.f();
if (i > 3 && i < 15) {
this.bU = i;
}
this.bV = packet204localeandviewdistance.g();
this.bW = packet204localeandviewdistance.h();
if (this.server.K() && this.server.J().equals(this.name)) {
this.server.c(packet204localeandviewdistance.i());
}
this.b(1, !packet204localeandviewdistance.j());
}
public int getChatFlags() {
return this.bV;
}
public void a(String s, int i) {
String s1 = s + "\0" + i; // CraftBukkit - fix decompile error
this.playerConnection.sendPacket(new Packet250CustomPayload("MC|TPack", s1.getBytes()));
}
public ChunkCoordinates b() {
return new ChunkCoordinates(MathHelper.floor(this.locX), MathHelper.floor(this.locY + 0.5D), MathHelper.floor(this.locZ));
}
// CraftBukkit start
public long timeOffset = 0;
public boolean relativeTime = true;
public long getPlayerTime() {
if (this.relativeTime) {
// Adds timeOffset to the current server time.
return this.world.getDayTime() + this.timeOffset;
} else {
// Adds timeOffset to the beginning of this day.
return this.world.getDayTime() - (this.world.getDayTime() % 24000) + this.timeOffset;
}
}
public WeatherType weather = null;
public WeatherType getPlayerWeather() {
return this.weather;
}
public void setPlayerWeather(WeatherType type, boolean plugin) {
if (!plugin && this.weather != null) {
return;
}
if (plugin) {
this.weather = type;
}
this.playerConnection.sendPacket(new Packet70Bed(type == WeatherType.DOWNFALL ? 1 : 2, 0));
}
public void resetPlayerWeather() {
this.weather = null;
this.setPlayerWeather(this.world.getWorldData().hasStorm() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false);
}
@Override
public String toString() {
return super.toString() + "(" + this.name + " at " + this.locX + "," + this.locY + "," + this.locZ + ")";
}
public void reset() {
float exp = 0;
boolean keepInventory = this.world.getGameRules().getBoolean("keepInventory");
if (this.keepLevel || keepInventory) {
exp = this.exp;
this.newTotalExp = this.expTotal;
this.newLevel = this.expLevel;
}
this.setHealth(this.getMaxHealth());
this.fireTicks = 0;
this.fallDistance = 0;
this.foodData = new FoodMetaData();
this.expLevel = this.newLevel;
this.expTotal = this.newTotalExp;
this.exp = 0;
this.deathTicks = 0;
this.aJ(); // Should be removeAllEffects.
this.updateEffects = true;
this.activeContainer = this.defaultContainer;
this.killer = null;
this.lastDamager = null;
this.combatTracker = new CombatTracker(this);
this.lastSentExp = -1;
if (this.keepLevel || keepInventory) {
this.exp = exp;
} else {
this.giveExp(this.newExp);
}
this.keepLevel = false;
}
@Override
public CraftPlayer getBukkitEntity() {
return (CraftPlayer) super.getBukkitEntity();
}
// CraftBukkit end
}