package net.minecraft.network;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import io.netty.buffer.Unpooled;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.Callable;
import net.minecraft.block.material.Material;
import net.minecraft.command.server.CommandBlockLogic;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityMinecartCommandBlock;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerBeacon;
import net.minecraft.inventory.ContainerMerchant;
import net.minecraft.inventory.ContainerRepair;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemEditableBook;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemWritableBook;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.play.INetHandlerPlayServer;
import net.minecraft.network.play.client.C00PacketKeepAlive;
import net.minecraft.network.play.client.C01PacketChatMessage;
import net.minecraft.network.play.client.C02PacketUseEntity;
import net.minecraft.network.play.client.C03PacketPlayer;
import net.minecraft.network.play.client.C07PacketPlayerDigging;
import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement;
import net.minecraft.network.play.client.C09PacketHeldItemChange;
import net.minecraft.network.play.client.C0APacketAnimation;
import net.minecraft.network.play.client.C0BPacketEntityAction;
import net.minecraft.network.play.client.C0CPacketInput;
import net.minecraft.network.play.client.C0DPacketCloseWindow;
import net.minecraft.network.play.client.C0EPacketClickWindow;
import net.minecraft.network.play.client.C0FPacketConfirmTransaction;
import net.minecraft.network.play.client.C10PacketCreativeInventoryAction;
import net.minecraft.network.play.client.C11PacketEnchantItem;
import net.minecraft.network.play.client.C12PacketUpdateSign;
import net.minecraft.network.play.client.C13PacketPlayerAbilities;
import net.minecraft.network.play.client.C14PacketTabComplete;
import net.minecraft.network.play.client.C15PacketClientSettings;
import net.minecraft.network.play.client.C16PacketClientStatus;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S00PacketKeepAlive;
import net.minecraft.network.play.server.S02PacketChat;
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraft.network.play.server.S2FPacketSetSlot;
import net.minecraft.network.play.server.S32PacketConfirmTransaction;
import net.minecraft.network.play.server.S3APacketTabComplete;
import net.minecraft.network.play.server.S40PacketDisconnect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.UserListBansEntry;
import net.minecraft.stats.AchievementList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityBeacon;
import net.minecraft.tileentity.TileEntityCommandBlock;
import net.minecraft.tileentity.TileEntitySign;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChatAllowedCharacters;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.IntHashMap;
import net.minecraft.util.ReportedException;
import net.minecraft.world.WorldServer;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
public class NetHandlerPlayServer implements INetHandlerPlayServer
{
private static final Logger logger = LogManager.getLogger();
public final NetworkManager netManager;
private final MinecraftServer serverController;
public EntityPlayerMP playerEntity;
private int networkTickCount;
/**
* Used to keep track of how the player is floating while gamerules should prevent that. Surpassing 80 ticks means
* kick
*/
private int floatingTickCount;
private boolean field_147366_g;
private int field_147378_h;
private long lastPingTime;
private static Random field_147376_j = new Random();
private long lastSentPingPacket;
/**
* Incremented by 20 each time a user sends a chat message, decreased by one every tick. Non-ops kicked when over
* 200
*/
private int chatSpamThresholdCount;
private int itemDropThreshold;
private IntHashMap field_147372_n = new IntHashMap();
private double lastPosX;
private double lastPosY;
private double lastPosZ;
private boolean hasMoved = true;
private static final String __OBFID = "CL_00001452";
public NetHandlerPlayServer(MinecraftServer server, NetworkManager networkManagerIn, EntityPlayerMP player)
{
this.serverController = server;
this.netManager = networkManagerIn;
networkManagerIn.setNetHandler(this);
this.playerEntity = player;
player.playerNetServerHandler = this;
}
/**
* For scheduled network tasks. Used in NetHandlerPlayServer to send keep-alive packets and in NetHandlerLoginServer
* for a login-timeout
*/
public void onNetworkTick()
{
this.field_147366_g = false;
++this.networkTickCount;
this.serverController.theProfiler.startSection("keepAlive");
if ((long)this.networkTickCount - this.lastSentPingPacket > 40L)
{
this.lastSentPingPacket = (long)this.networkTickCount;
this.lastPingTime = this.currentTimeMillis();
this.field_147378_h = (int)this.lastPingTime;
this.sendPacket(new S00PacketKeepAlive(this.field_147378_h));
}
if (this.chatSpamThresholdCount > 0)
{
--this.chatSpamThresholdCount;
}
if (this.itemDropThreshold > 0)
{
--this.itemDropThreshold;
}
if (this.playerEntity.getLastActiveTime() > 0L && this.serverController.getMaxPlayerIdleMinutes() > 0 && MinecraftServer.getCurrentTimeMillis() - this.playerEntity.getLastActiveTime() > (long)(this.serverController.getMaxPlayerIdleMinutes() * 1000 * 60))
{
this.kickPlayerFromServer("You have been idle for too long!");
}
}
public NetworkManager getNetworkManager()
{
return this.netManager;
}
/**
* Kick a player from the server with a reason
*/
public void kickPlayerFromServer(String reason)
{
final ChatComponentText chatcomponenttext = new ChatComponentText(reason);
this.netManager.scheduleOutboundPacket(new S40PacketDisconnect(chatcomponenttext), new GenericFutureListener[] {new GenericFutureListener()
{
private static final String __OBFID = "CL_00001453";
public void operationComplete(Future p_operationComplete_1_)
{
NetHandlerPlayServer.this.netManager.closeChannel(chatcomponenttext);
}
}
});
this.netManager.disableAutoRead();
}
/**
* Processes player movement input. Includes walking, strafing, jumping, sneaking; excludes riding and toggling
* flying/sprinting
*/
public void processInput(C0CPacketInput packetIn)
{
this.playerEntity.setEntityActionState(packetIn.getStrafeSpeed(), packetIn.getForwardSpeed(), packetIn.isJumping(), packetIn.isSneaking());
}
/**
* Processes clients perspective on player positioning and/or orientation
*/
public void processPlayer(C03PacketPlayer packetIn)
{
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
this.field_147366_g = true;
if (!this.playerEntity.playerConqueredTheEnd)
{
double d0;
if (!this.hasMoved)
{
d0 = packetIn.getPositionY() - this.lastPosY;
if (packetIn.getPositionX() == this.lastPosX && d0 * d0 < 0.01D && packetIn.getPositionZ() == this.lastPosZ)
{
this.hasMoved = true;
}
}
if (this.hasMoved)
{
double d1;
double d2;
double d3;
if (this.playerEntity.ridingEntity != null)
{
float f4 = this.playerEntity.rotationYaw;
float f = this.playerEntity.rotationPitch;
this.playerEntity.ridingEntity.updateRiderPosition();
d1 = this.playerEntity.posX;
d2 = this.playerEntity.posY;
d3 = this.playerEntity.posZ;
if (packetIn.getRotating())
{
f4 = packetIn.getYaw();
f = packetIn.getPitch();
}
this.playerEntity.onGround = packetIn.func_149465_i();
this.playerEntity.onUpdateEntity();
this.playerEntity.yOffset2 = 0.0F;
this.playerEntity.setPositionAndRotation(d1, d2, d3, f4, f);
if (this.playerEntity.ridingEntity != null)
{
this.playerEntity.ridingEntity.updateRiderPosition();
}
if (!this.hasMoved) //Fixes teleportation kick while riding entities
{
return;
}
this.serverController.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
if (this.hasMoved)
{
this.lastPosX = this.playerEntity.posX;
this.lastPosY = this.playerEntity.posY;
this.lastPosZ = this.playerEntity.posZ;
}
worldserver.updateEntity(this.playerEntity);
return;
}
if (this.playerEntity.isPlayerSleeping())
{
this.playerEntity.onUpdateEntity();
this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
worldserver.updateEntity(this.playerEntity);
return;
}
d0 = this.playerEntity.posY;
this.lastPosX = this.playerEntity.posX;
this.lastPosY = this.playerEntity.posY;
this.lastPosZ = this.playerEntity.posZ;
d1 = this.playerEntity.posX;
d2 = this.playerEntity.posY;
d3 = this.playerEntity.posZ;
float f1 = this.playerEntity.rotationYaw;
float f2 = this.playerEntity.rotationPitch;
if (packetIn.func_149466_j() && packetIn.getPositionY() == -999.0D && packetIn.getStance() == -999.0D)
{
packetIn.func_149469_a(false);
}
double d4;
if (packetIn.func_149466_j())
{
d1 = packetIn.getPositionX();
d2 = packetIn.getPositionY();
d3 = packetIn.getPositionZ();
d4 = packetIn.getStance() - packetIn.getPositionY();
if (!this.playerEntity.isPlayerSleeping() && (d4 > 1.65D || d4 < 0.1D))
{
this.kickPlayerFromServer("Illegal stance");
logger.warn(this.playerEntity.getCommandSenderName() + " had an illegal stance: " + d4);
return;
}
if (Math.abs(packetIn.getPositionX()) > 3.2E7D || Math.abs(packetIn.getPositionZ()) > 3.2E7D)
{
this.kickPlayerFromServer("Illegal position");
return;
}
}
if (packetIn.getRotating())
{
f1 = packetIn.getYaw();
f2 = packetIn.getPitch();
}
this.playerEntity.onUpdateEntity();
this.playerEntity.yOffset2 = 0.0F;
this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, f1, f2);
if (!this.hasMoved)
{
return;
}
d4 = d1 - this.playerEntity.posX;
double d5 = d2 - this.playerEntity.posY;
double d6 = d3 - this.playerEntity.posZ;
//BUGFIX: min -> max, grabs the highest distance
double d7 = Math.max(Math.abs(d4), Math.abs(this.playerEntity.motionX));
double d8 = Math.max(Math.abs(d5), Math.abs(this.playerEntity.motionY));
double d9 = Math.max(Math.abs(d6), Math.abs(this.playerEntity.motionZ));
double d10 = d7 * d7 + d8 * d8 + d9 * d9;
if (d10 > 100.0D && (!this.serverController.isSinglePlayer() || !this.serverController.getServerOwner().equals(this.playerEntity.getCommandSenderName())))
{
logger.warn(this.playerEntity.getCommandSenderName() + " moved too quickly! " + d4 + "," + d5 + "," + d6 + " (" + d7 + ", " + d8 + ", " + d9 + ")");
this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
return;
}
float f3 = 0.0625F;
boolean flag = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)f3, (double)f3, (double)f3)).isEmpty();
if (this.playerEntity.onGround && !packetIn.func_149465_i() && d5 > 0.0D)
{
this.playerEntity.jump();
}
if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
{
return;
}
this.playerEntity.moveEntity(d4, d5, d6);
this.playerEntity.onGround = packetIn.func_149465_i();
this.playerEntity.addMovementStat(d4, d5, d6);
double d11 = d5;
d4 = d1 - this.playerEntity.posX;
d5 = d2 - this.playerEntity.posY;
if (d5 > -0.5D || d5 < 0.5D)
{
d5 = 0.0D;
}
d6 = d3 - this.playerEntity.posZ;
d10 = d4 * d4 + d5 * d5 + d6 * d6;
boolean flag1 = false;
if (d10 > 0.0625D && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.theItemInWorldManager.isCreative())
{
flag1 = true;
logger.warn(this.playerEntity.getCommandSenderName() + " moved wrongly!");
}
if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
{
return;
}
this.playerEntity.setPositionAndRotation(d1, d2, d3, f1, f2);
boolean flag2 = worldserver.getCollidingBoundingBoxes(this.playerEntity, this.playerEntity.boundingBox.copy().contract((double)f3, (double)f3, (double)f3)).isEmpty();
if (flag && (flag1 || !flag2) && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.noClip)
{
this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, f1, f2);
return;
}
AxisAlignedBB axisalignedbb = this.playerEntity.boundingBox.copy().expand((double)f3, (double)f3, (double)f3).addCoord(0.0D, -0.55D, 0.0D);
if (!this.serverController.isFlightAllowed() && !this.playerEntity.theItemInWorldManager.isCreative() && !worldserver.checkBlockCollision(axisalignedbb) && !this.playerEntity.capabilities.allowFlying)
{
if (d11 >= -0.03125D)
{
++this.floatingTickCount;
if (this.floatingTickCount > 80)
{
logger.warn(this.playerEntity.getCommandSenderName() + " was kicked for floating too long!");
this.kickPlayerFromServer("Flying is not enabled on this server");
return;
}
}
}
else
{
this.floatingTickCount = 0;
}
if (!this.hasMoved) //Fixes "Moved Too Fast" kick when being teleported while moving
{
return;
}
this.playerEntity.onGround = packetIn.func_149465_i();
this.serverController.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
this.playerEntity.handleFalling(this.playerEntity.posY - d0, packetIn.func_149465_i());
}
else if (this.networkTickCount % 20 == 0)
{
this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
}
}
}
public void setPlayerLocation(double x, double y, double z, float yaw, float pitch)
{
this.hasMoved = false;
this.lastPosX = x;
this.lastPosY = y;
this.lastPosZ = z;
this.playerEntity.setPositionAndRotation(x, y, z, yaw, pitch);
this.playerEntity.playerNetServerHandler.sendPacket(new S08PacketPlayerPosLook(x, y + 1.6200000047683716D, z, yaw, pitch, false));
}
/**
* Processes the player initiating/stopping digging on a particular spot, as well as a player dropping items?. (0:
* initiated, 1: reinitiated, 2? , 3-4 drop item (respectively without or with player control), 5: stopped; x,y,z,
* side clicked on;)
*/
public void processPlayerDigging(C07PacketPlayerDigging packetIn)
{
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
this.playerEntity.markPlayerActive();
if (packetIn.getDiggedBlockStatus() == 4)
{
this.playerEntity.dropOneItem(false);
}
else if (packetIn.getDiggedBlockStatus() == 3)
{
this.playerEntity.dropOneItem(true);
}
else if (packetIn.getDiggedBlockStatus() == 5)
{
this.playerEntity.stopUsingItem();
}
else
{
boolean flag = false;
if (packetIn.getDiggedBlockStatus() == 0)
{
flag = true;
}
if (packetIn.getDiggedBlockStatus() == 1)
{
flag = true;
}
if (packetIn.getDiggedBlockStatus() == 2)
{
flag = true;
}
int i = packetIn.getDiggedBlockX();
int j = packetIn.getDiggedBlockY();
int k = packetIn.getDiggedBlockZ();
if (flag)
{
double d0 = this.playerEntity.posX - ((double)i + 0.5D);
double d1 = this.playerEntity.posY - ((double)j + 0.5D) + 1.5D;
double d2 = this.playerEntity.posZ - ((double)k + 0.5D);
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
dist *= dist;
if (d3 > dist)
{
return;
}
if (j >= this.serverController.getBuildLimit())
{
return;
}
}
if (packetIn.getDiggedBlockStatus() == 0)
{
if (!this.serverController.isBlockProtected(worldserver, i, j, k, this.playerEntity))
{
this.playerEntity.theItemInWorldManager.onBlockClicked(i, j, k, packetIn.getDiggingBlockFace());
}
else
{
this.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver));
}
}
else if (packetIn.getDiggedBlockStatus() == 2)
{
this.playerEntity.theItemInWorldManager.blockRemoving(i, j, k);
if (worldserver.getBlock(i, j, k).getMaterial() != Material.air)
{
this.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver));
}
}
else if (packetIn.getDiggedBlockStatus() == 1)
{
this.playerEntity.theItemInWorldManager.cancelDestroyingBlock(i, j, k);
if (worldserver.getBlock(i, j, k).getMaterial() != Material.air)
{
this.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver));
}
}
}
}
/**
* Processes block placement and block activation (anvil, furnace, etc.)
*/
public void processPlayerBlockPlacement(C08PacketPlayerBlockPlacement packetIn)
{
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
ItemStack itemstack = this.playerEntity.inventory.getCurrentItem();
boolean flag = false;
boolean placeResult = true;
int i = packetIn.getPlacedBlockX();
int j = packetIn.getPlacedBlockY();
int k = packetIn.getPlacedBlockZ();
int l = packetIn.getPlacedBlockDirection();
this.playerEntity.markPlayerActive();
if (packetIn.getPlacedBlockDirection() == 255)
{
if (itemstack == null)
{
return;
}
PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(playerEntity, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, 0, 0, 0, -1, worldserver);
if (event.useItem != Event.Result.DENY)
{
this.playerEntity.theItemInWorldManager.tryUseItem(this.playerEntity, worldserver, itemstack);
}
}
else if (packetIn.getPlacedBlockY() >= this.serverController.getBuildLimit() - 1 && (packetIn.getPlacedBlockDirection() == 1 || packetIn.getPlacedBlockY() >= this.serverController.getBuildLimit()))
{
ChatComponentTranslation chatcomponenttranslation = new ChatComponentTranslation("build.tooHigh", new Object[] {Integer.valueOf(this.serverController.getBuildLimit())});
chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
this.playerEntity.playerNetServerHandler.sendPacket(new S02PacketChat(chatcomponenttranslation));
flag = true;
}
else
{
double dist = playerEntity.theItemInWorldManager.getBlockReachDistance() + 1;
dist *= dist;
if (this.hasMoved && this.playerEntity.getDistanceSq((double)i + 0.5D, (double)j + 0.5D, (double)k + 0.5D) < dist && !this.serverController.isBlockProtected(worldserver, i, j, k, this.playerEntity))
{
// record block place result so we can update client itemstack size if place event was cancelled.
if (!this.playerEntity.theItemInWorldManager.activateBlockOrUseItem(this.playerEntity, worldserver, itemstack, i, j, k, l, packetIn.getPlacedBlockOffsetX(), packetIn.getPlacedBlockOffsetY(), packetIn.getPlacedBlockOffsetZ()))
{
placeResult = false;
}
}
flag = true;
}
if (flag)
{
this.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver));
if (l == 0)
{
--j;
}
if (l == 1)
{
++j;
}
if (l == 2)
{
--k;
}
if (l == 3)
{
++k;
}
if (l == 4)
{
--i;
}
if (l == 5)
{
++i;
}
this.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver));
}
itemstack = this.playerEntity.inventory.getCurrentItem();
if (itemstack != null && itemstack.stackSize == 0)
{
this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = null;
itemstack = null;
}
if (itemstack == null || itemstack.getMaxItemUseDuration() == 0)
{
this.playerEntity.isChangingQuantityOnly = true;
this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = ItemStack.copyItemStack(this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem]);
Slot slot = this.playerEntity.openContainer.getSlotFromInventory(this.playerEntity.inventory, this.playerEntity.inventory.currentItem);
this.playerEntity.openContainer.detectAndSendChanges();
this.playerEntity.isChangingQuantityOnly = false;
if (!ItemStack.areItemStacksEqual(this.playerEntity.inventory.getCurrentItem(), packetIn.getStack()) || !placeResult) // force client itemstack update if place event was cancelled
{
this.sendPacket(new S2FPacketSetSlot(this.playerEntity.openContainer.windowId, slot.slotNumber, this.playerEntity.inventory.getCurrentItem()));
}
}
}
/**
* Invoked when disconnecting, the parameter is a ChatComponent describing the reason for termination
*/
public void onDisconnect(IChatComponent reason)
{
logger.info(this.playerEntity.getCommandSenderName() + " lost connection: " + reason);
this.serverController.refreshStatusNextTick();
ChatComponentTranslation chatcomponenttranslation = new ChatComponentTranslation("multiplayer.player.left", new Object[] {this.playerEntity.getFormattedCommandSenderName()});
chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.YELLOW);
this.serverController.getConfigurationManager().sendChatMsg(chatcomponenttranslation);
this.playerEntity.mountEntityAndWakeUp();
this.serverController.getConfigurationManager().playerLoggedOut(this.playerEntity);
if (this.serverController.isSinglePlayer() && this.playerEntity.getCommandSenderName().equals(this.serverController.getServerOwner()))
{
logger.info("Stopping singleplayer server as player logged out");
this.serverController.initiateShutdown();
}
}
public void sendPacket(final Packet packetIn)
{
if (packetIn instanceof S02PacketChat)
{
S02PacketChat s02packetchat = (S02PacketChat)packetIn;
EntityPlayer.EnumChatVisibility enumchatvisibility = this.playerEntity.func_147096_v();
if (enumchatvisibility == EntityPlayer.EnumChatVisibility.HIDDEN)
{
return;
}
if (enumchatvisibility == EntityPlayer.EnumChatVisibility.SYSTEM && !s02packetchat.isChat())
{
return;
}
}
try
{
this.netManager.scheduleOutboundPacket(packetIn, new GenericFutureListener[0]);
}
catch (Throwable throwable)
{
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Sending packet");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Packet being sent");
crashreportcategory.addCrashSectionCallable("Packet class", new Callable()
{
private static final String __OBFID = "CL_00001454";
public String call()
{
return packetIn.getClass().getCanonicalName();
}
});
throw new ReportedException(crashreport);
}
}
/**
* Updates which quickbar slot is selected
*/
public void processHeldItemChange(C09PacketHeldItemChange packetIn)
{
if (packetIn.getSlotId() >= 0 && packetIn.getSlotId() < InventoryPlayer.getHotbarSize())
{
this.playerEntity.inventory.currentItem = packetIn.getSlotId();
this.playerEntity.markPlayerActive();
}
else
{
logger.warn(this.playerEntity.getCommandSenderName() + " tried to set an invalid carried item");
}
}
/**
* Process chat messages (broadcast back to clients) and commands (executes)
*/
public void processChatMessage(C01PacketChatMessage packetIn)
{
if (this.playerEntity.func_147096_v() == EntityPlayer.EnumChatVisibility.HIDDEN)
{
ChatComponentTranslation chatcomponenttranslation = new ChatComponentTranslation("chat.cannotSend", new Object[0]);
chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
this.sendPacket(new S02PacketChat(chatcomponenttranslation));
}
else
{
this.playerEntity.markPlayerActive();
String s = packetIn.getMessage();
s = StringUtils.normalizeSpace(s);
for (int i = 0; i < s.length(); ++i)
{
if (!ChatAllowedCharacters.isAllowedCharacter(s.charAt(i)))
{
this.kickPlayerFromServer("Illegal characters in chat");
return;
}
}
if (s.startsWith("/"))
{
this.handleSlashCommand(s);
}
else
{
ChatComponentTranslation chatcomponenttranslation1 = new ChatComponentTranslation("chat.type.text", new Object[] {this.playerEntity.getFormattedCommandSenderName(), ForgeHooks.newChatWithLinks(s)}); // Fixes chat links
chatcomponenttranslation1 = ForgeHooks.onServerChatEvent(this, s, chatcomponenttranslation1);
if (chatcomponenttranslation1 == null) return;
this.serverController.getConfigurationManager().sendChatMsgImpl(chatcomponenttranslation1, false);
}
this.chatSpamThresholdCount += 20;
if (this.chatSpamThresholdCount > 200 && !this.serverController.getConfigurationManager().canSendCommands(this.playerEntity.getGameProfile()))
{
this.kickPlayerFromServer("disconnect.spam");
}
}
}
/**
* Handle commands that start with a /
*/
private void handleSlashCommand(String command)
{
this.serverController.getCommandManager().executeCommand(this.playerEntity, command);
}
/**
* Processes the player swinging its held item
*/
public void processAnimation(C0APacketAnimation packetIn)
{
this.playerEntity.markPlayerActive();
if (packetIn.getType() == 1)
{
this.playerEntity.swingItem();
}
}
/**
* Processes a range of action-types: sneaking, sprinting, waking from sleep, opening the inventory or setting jump
* height of the horse the player is riding
*/
public void processEntityAction(C0BPacketEntityAction packetIn)
{
this.playerEntity.markPlayerActive();
if (packetIn.func_149513_d() == 1)
{
this.playerEntity.setSneaking(true);
}
else if (packetIn.func_149513_d() == 2)
{
this.playerEntity.setSneaking(false);
}
else if (packetIn.func_149513_d() == 4)
{
this.playerEntity.setSprinting(true);
}
else if (packetIn.func_149513_d() == 5)
{
this.playerEntity.setSprinting(false);
}
else if (packetIn.func_149513_d() == 3)
{
this.playerEntity.wakeUpPlayer(false, true, true);
this.hasMoved = false;
}
else if (packetIn.func_149513_d() == 6)
{
if (this.playerEntity.ridingEntity != null && this.playerEntity.ridingEntity instanceof EntityHorse)
{
((EntityHorse)this.playerEntity.ridingEntity).setJumpPower(packetIn.func_149512_e());
}
}
else if (packetIn.func_149513_d() == 7 && this.playerEntity.ridingEntity != null && this.playerEntity.ridingEntity instanceof EntityHorse)
{
((EntityHorse)this.playerEntity.ridingEntity).openGUI(this.playerEntity);
}
}
/**
* Processes interactions ((un)leashing, opening command block GUI) and attacks on an entity with players currently
* equipped item
*/
public void processUseEntity(C02PacketUseEntity packetIn)
{
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
Entity entity = packetIn.getEntityFromWorld(worldserver);
this.playerEntity.markPlayerActive();
if (entity != null)
{
boolean flag = this.playerEntity.canEntityBeSeen(entity);
double d0 = 36.0D;
if (!flag)
{
d0 = 9.0D;
}
if (this.playerEntity.getDistanceSqToEntity(entity) < d0)
{
if (packetIn.getAction() == C02PacketUseEntity.Action.INTERACT)
{
this.playerEntity.interactWith(entity);
}
else if (packetIn.getAction() == C02PacketUseEntity.Action.ATTACK)
{
if (entity instanceof EntityItem || entity instanceof EntityXPOrb || entity instanceof EntityArrow || entity == this.playerEntity)
{
this.kickPlayerFromServer("Attempting to attack an invalid entity");
this.serverController.logWarning("Player " + this.playerEntity.getCommandSenderName() + " tried to attack an invalid entity");
return;
}
this.playerEntity.attackTargetEntityWithCurrentItem(entity);
}
}
}
}
/**
* Processes the client status updates: respawn attempt from player, opening statistics or achievements, or
* acquiring 'open inventory' achievement
*/
public void processClientStatus(C16PacketClientStatus packetIn)
{
this.playerEntity.markPlayerActive();
C16PacketClientStatus.EnumState enumstate = packetIn.getStatus();
switch (NetHandlerPlayServer.SwitchEnumState.field_151290_a[enumstate.ordinal()])
{
case 1:
if (this.playerEntity.playerConqueredTheEnd)
{
this.playerEntity = this.serverController.getConfigurationManager().recreatePlayerEntity(this.playerEntity, 0, true);
}
else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled())
{
if (this.serverController.isSinglePlayer() && this.playerEntity.getCommandSenderName().equals(this.serverController.getServerOwner()))
{
this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
this.serverController.deleteWorldAndStopServer();
}
else
{
UserListBansEntry userlistbansentry = new UserListBansEntry(this.playerEntity.getGameProfile(), (Date)null, "(You just lost the game)", (Date)null, "Death in Hardcore");
this.serverController.getConfigurationManager().getBannedPlayers().addEntry(userlistbansentry);
this.playerEntity.playerNetServerHandler.kickPlayerFromServer("You have died. Game over, man, it\'s game over!");
}
}
else
{
if (this.playerEntity.getHealth() > 0.0F)
{
return;
}
this.playerEntity = this.serverController.getConfigurationManager().recreatePlayerEntity(this.playerEntity, playerEntity.dimension, false);
}
break;
case 2:
this.playerEntity.getStatFile().func_150876_a(this.playerEntity);
break;
case 3:
this.playerEntity.triggerAchievement(AchievementList.openInventory);
}
}
/**
* Processes the client closing windows (container)
*/
public void processCloseWindow(C0DPacketCloseWindow packetIn)
{
this.playerEntity.closeContainer();
}
/**
* Executes a container/inventory slot manipulation as indicated by the packet. Sends the serverside result if they
* didn't match the indicated result and prevents further manipulation by the player until he confirms that it has
* the same open container/inventory
*/
public void processClickWindow(C0EPacketClickWindow packetIn)
{
this.playerEntity.markPlayerActive();
if (this.playerEntity.openContainer.windowId == packetIn.getWindowId() && this.playerEntity.openContainer.getCanCraft(this.playerEntity))
{
ItemStack itemstack = this.playerEntity.openContainer.slotClick(packetIn.getSlotId(), packetIn.getUsedButton(), packetIn.getMode(), this.playerEntity);
if (ItemStack.areItemStacksEqual(packetIn.getClickedItem(), itemstack))
{
this.playerEntity.playerNetServerHandler.sendPacket(new S32PacketConfirmTransaction(packetIn.getWindowId(), packetIn.getActionNumber(), true));
this.playerEntity.isChangingQuantityOnly = true;
this.playerEntity.openContainer.detectAndSendChanges();
this.playerEntity.updateHeldItem();
this.playerEntity.isChangingQuantityOnly = false;
}
else
{
this.field_147372_n.addKey(this.playerEntity.openContainer.windowId, Short.valueOf(packetIn.getActionNumber()));
this.playerEntity.playerNetServerHandler.sendPacket(new S32PacketConfirmTransaction(packetIn.getWindowId(), packetIn.getActionNumber(), false));
this.playerEntity.openContainer.setCanCraft(this.playerEntity, false);
ArrayList arraylist = new ArrayList();
for (int i = 0; i < this.playerEntity.openContainer.inventorySlots.size(); ++i)
{
arraylist.add(((Slot)this.playerEntity.openContainer.inventorySlots.get(i)).getStack());
}
this.playerEntity.updateCraftingInventory(this.playerEntity.openContainer, arraylist);
}
}
}
/**
* Enchants the item identified by the packet given some convoluted conditions (matching window, which
* should/shouldn't be in use?)
*/
public void processEnchantItem(C11PacketEnchantItem packetIn)
{
this.playerEntity.markPlayerActive();
if (this.playerEntity.openContainer.windowId == packetIn.getId() && this.playerEntity.openContainer.getCanCraft(this.playerEntity))
{
this.playerEntity.openContainer.enchantItem(this.playerEntity, packetIn.getButton());
this.playerEntity.openContainer.detectAndSendChanges();
}
}
/**
* Update the server with an ItemStack in a slot.
*/
public void processCreativeInventoryAction(C10PacketCreativeInventoryAction packetIn)
{
if (this.playerEntity.theItemInWorldManager.isCreative())
{
boolean flag = packetIn.getSlotId() < 0;
ItemStack itemstack = packetIn.getStack();
boolean flag1 = packetIn.getSlotId() >= 1 && packetIn.getSlotId() < 36 + InventoryPlayer.getHotbarSize();
boolean flag2 = itemstack == null || itemstack.getItem() != null;
boolean flag3 = itemstack == null || itemstack.getMetadata() >= 0 && itemstack.stackSize <= 64 && itemstack.stackSize > 0;
if (flag1 && flag2 && flag3)
{
if (itemstack == null)
{
this.playerEntity.inventoryContainer.putStackInSlot(packetIn.getSlotId(), (ItemStack)null);
}
else
{
this.playerEntity.inventoryContainer.putStackInSlot(packetIn.getSlotId(), itemstack);
}
this.playerEntity.inventoryContainer.setCanCraft(this.playerEntity, true);
}
else if (flag && flag2 && flag3 && this.itemDropThreshold < 200)
{
this.itemDropThreshold += 20;
EntityItem entityitem = this.playerEntity.dropPlayerItemWithRandomChoice(itemstack, true);
if (entityitem != null)
{
entityitem.setAgeToCreativeDespawnTime();
}
}
}
}
/**
* Received in response to the server requesting to confirm that the client-side open container matches the servers'
* after a mismatched container-slot manipulation. It will unlock the player's ability to manipulate the container
* contents
*/
public void processConfirmTransaction(C0FPacketConfirmTransaction packetIn)
{
Short oshort = (Short)this.field_147372_n.lookup(this.playerEntity.openContainer.windowId);
if (oshort != null && packetIn.getUid() == oshort.shortValue() && this.playerEntity.openContainer.windowId == packetIn.getId() && !this.playerEntity.openContainer.getCanCraft(this.playerEntity))
{
this.playerEntity.openContainer.setCanCraft(this.playerEntity, true);
}
}
public void processUpdateSign(C12PacketUpdateSign packetIn)
{
this.playerEntity.markPlayerActive();
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
if (worldserver.blockExists(packetIn.getX(), packetIn.getY(), packetIn.getZ()))
{
TileEntity tileentity = worldserver.getTileEntity(packetIn.getX(), packetIn.getY(), packetIn.getZ());
if (tileentity instanceof TileEntitySign)
{
TileEntitySign tileentitysign = (TileEntitySign)tileentity;
if (!tileentitysign.getIsEditable() || tileentitysign.func_145911_b() != this.playerEntity)
{
this.serverController.logWarning("Player " + this.playerEntity.getCommandSenderName() + " just tried to change non-editable sign");
return;
}
}
int i;
int j;
for (j = 0; j < 4; ++j)
{
boolean flag = true;
if (packetIn.getLines()[j].length() > 15)
{
flag = false;
}
else
{
for (i = 0; i < packetIn.getLines()[j].length(); ++i)
{
if (!ChatAllowedCharacters.isAllowedCharacter(packetIn.getLines()[j].charAt(i)))
{
flag = false;
}
}
}
if (!flag)
{
packetIn.getLines()[j] = "!?";
}
}
if (tileentity instanceof TileEntitySign)
{
j = packetIn.getX();
int k = packetIn.getY();
i = packetIn.getZ();
TileEntitySign tileentitysign1 = (TileEntitySign)tileentity;
System.arraycopy(packetIn.getLines(), 0, tileentitysign1.signText, 0, 4);
tileentitysign1.markDirty();
worldserver.markBlockForUpdate(j, k, i);
}
}
}
/**
* Updates a players' ping statistics
*/
public void processKeepAlive(C00PacketKeepAlive packetIn)
{
if (packetIn.getKey() == this.field_147378_h)
{
int i = (int)(this.currentTimeMillis() - this.lastPingTime);
this.playerEntity.ping = (this.playerEntity.ping * 3 + i) / 4;
}
}
private long currentTimeMillis()
{
return System.nanoTime() / 1000000L;
}
/**
* Processes a player starting/stopping flying
*/
public void processPlayerAbilities(C13PacketPlayerAbilities packetIn)
{
this.playerEntity.capabilities.isFlying = packetIn.isFlying() && this.playerEntity.capabilities.allowFlying;
}
/**
* Retrieves possible tab completions for the requested command string and sends them to the client
*/
public void processTabComplete(C14PacketTabComplete packetIn)
{
ArrayList arraylist = Lists.newArrayList();
Iterator iterator = this.serverController.getPossibleCompletions(this.playerEntity, packetIn.getMessage()).iterator();
while (iterator.hasNext())
{
String s = (String)iterator.next();
arraylist.add(s);
}
this.playerEntity.playerNetServerHandler.sendPacket(new S3APacketTabComplete((String[])arraylist.toArray(new String[arraylist.size()])));
}
/**
* Updates serverside copy of client settings: language, render distance, chat visibility, chat colours, difficulty,
* and whether to show the cape
*/
public void processClientSettings(C15PacketClientSettings packetIn)
{
this.playerEntity.func_147100_a(packetIn);
}
/**
* Synchronizes serverside and clientside book contents and signing
*/
public void processVanilla250Packet(C17PacketCustomPayload packetIn)
{
PacketBuffer packetbuffer;
ItemStack itemstack;
ItemStack itemstack1;
if ("MC|BEdit".equals(packetIn.getChannel()))
{
packetbuffer = new PacketBuffer(Unpooled.wrappedBuffer(packetIn.getData()));
try
{
itemstack = packetbuffer.readItemStackFromBuffer();
if (itemstack != null)
{
if (!ItemWritableBook.validBookPageTagContents(itemstack.getTagCompound()))
{
throw new IOException("Invalid book tag!");
}
itemstack1 = this.playerEntity.inventory.getCurrentItem();
if (itemstack1 == null)
{
return;
}
if (itemstack.getItem() == Items.writable_book && itemstack.getItem() == itemstack1.getItem())
{
itemstack1.setTagInfo("pages", itemstack.getTagCompound().getTagList("pages", 8));
}
return;
}
}
catch (Exception exception4)
{
logger.error("Couldn\'t handle book info", exception4);
return;
}
finally
{
packetbuffer.release();
}
return;
}
else if ("MC|BSign".equals(packetIn.getChannel()))
{
packetbuffer = new PacketBuffer(Unpooled.wrappedBuffer(packetIn.getData()));
try
{
itemstack = packetbuffer.readItemStackFromBuffer();
if (itemstack == null)
{
return;
}
if (!ItemEditableBook.validBookTagContents(itemstack.getTagCompound()))
{
throw new IOException("Invalid book tag!");
}
itemstack1 = this.playerEntity.inventory.getCurrentItem();
if (itemstack1 != null)
{
if (itemstack.getItem() == Items.written_book && itemstack1.getItem() == Items.writable_book)
{
itemstack1.setTagInfo("author", new NBTTagString(this.playerEntity.getCommandSenderName()));
itemstack1.setTagInfo("title", new NBTTagString(itemstack.getTagCompound().getString("title")));
itemstack1.setTagInfo("pages", itemstack.getTagCompound().getTagList("pages", 8));
itemstack1.setItem(Items.written_book);
}
return;
}
}
catch (Exception exception3)
{
logger.error("Couldn\'t sign book", exception3);
return;
}
finally
{
packetbuffer.release();
}
return;
}
else
{
DataInputStream datainputstream;
int i;
if ("MC|TrSel".equals(packetIn.getChannel()))
{
try
{
datainputstream = new DataInputStream(new ByteArrayInputStream(packetIn.getData()));
i = datainputstream.readInt();
Container container = this.playerEntity.openContainer;
if (container instanceof ContainerMerchant)
{
((ContainerMerchant)container).setCurrentRecipeIndex(i);
}
}
catch (Exception exception2)
{
logger.error("Couldn\'t select trade", exception2);
}
}
else if ("MC|AdvCdm".equals(packetIn.getChannel()))
{
if (!this.serverController.isCommandBlockEnabled())
{
this.playerEntity.addChatMessage(new ChatComponentTranslation("advMode.notEnabled", new Object[0]));
}
else if (this.playerEntity.canCommandSenderUseCommand(2, "") && this.playerEntity.capabilities.isCreativeMode)
{
packetbuffer = new PacketBuffer(Unpooled.wrappedBuffer(packetIn.getData()));
try
{
byte b0 = packetbuffer.readByte();
CommandBlockLogic commandblocklogic = null;
if (b0 == 0)
{
TileEntity tileentity = this.playerEntity.worldObj.getTileEntity(packetbuffer.readInt(), packetbuffer.readInt(), packetbuffer.readInt());
if (tileentity instanceof TileEntityCommandBlock)
{
commandblocklogic = ((TileEntityCommandBlock)tileentity).func_145993_a();
}
}
else if (b0 == 1)
{
Entity entity = this.playerEntity.worldObj.getEntityByID(packetbuffer.readInt());
if (entity instanceof EntityMinecartCommandBlock)
{
commandblocklogic = ((EntityMinecartCommandBlock)entity).func_145822_e();
}
}
String s1 = packetbuffer.readStringFromBuffer(packetbuffer.readableBytes());
if (commandblocklogic != null)
{
commandblocklogic.setCommand(s1);
commandblocklogic.func_145756_e();
this.playerEntity.addChatMessage(new ChatComponentTranslation("advMode.setCommand.success", new Object[] {s1}));
}
}
catch (Exception exception1)
{
logger.error("Couldn\'t set command block", exception1);
}
finally
{
packetbuffer.release();
}
}
else
{
this.playerEntity.addChatMessage(new ChatComponentTranslation("advMode.notAllowed", new Object[0]));
}
}
else if ("MC|Beacon".equals(packetIn.getChannel()))
{
if (this.playerEntity.openContainer instanceof ContainerBeacon)
{
try
{
datainputstream = new DataInputStream(new ByteArrayInputStream(packetIn.getData()));
i = datainputstream.readInt();
int j = datainputstream.readInt();
ContainerBeacon containerbeacon = (ContainerBeacon)this.playerEntity.openContainer;
Slot slot = containerbeacon.getSlot(0);
if (slot.getHasStack())
{
slot.decrStackSize(1);
TileEntityBeacon tileentitybeacon = containerbeacon.func_148327_e();
tileentitybeacon.setPrimaryEffect(i);
tileentitybeacon.setSecondaryEffect(j);
tileentitybeacon.markDirty();
}
}
catch (Exception exception)
{
logger.error("Couldn\'t set beacon", exception);
}
}
}
else if ("MC|ItemName".equals(packetIn.getChannel()) && this.playerEntity.openContainer instanceof ContainerRepair)
{
ContainerRepair containerrepair = (ContainerRepair)this.playerEntity.openContainer;
if (packetIn.getData() != null && packetIn.getData().length >= 1)
{
String s = ChatAllowedCharacters.filterAllowedCharacters(new String(packetIn.getData(), Charsets.UTF_8));
if (s.length() <= 30)
{
containerrepair.updateItemName(s);
}
}
else
{
containerrepair.updateItemName("");
}
}
}
}
/**
* Allows validation of the connection state transition. Parameters: from, to (connection state). Typically throws
* IllegalStateException or UnsupportedOperationException if validation fails
*/
public void onConnectionStateTransition(EnumConnectionState oldState, EnumConnectionState newState)
{
if (newState != EnumConnectionState.PLAY)
{
throw new IllegalStateException("Unexpected change in protocol!");
}
}
static final class SwitchEnumState
{
static final int[] field_151290_a = new int[C16PacketClientStatus.EnumState.values().length];
private static final String __OBFID = "CL_00001455";
static
{
try
{
field_151290_a[C16PacketClientStatus.EnumState.PERFORM_RESPAWN.ordinal()] = 1;
}
catch (NoSuchFieldError var3)
{
;
}
try
{
field_151290_a[C16PacketClientStatus.EnumState.REQUEST_STATS.ordinal()] = 2;
}
catch (NoSuchFieldError var2)
{
;
}
try
{
field_151290_a[C16PacketClientStatus.EnumState.OPEN_INVENTORY_ACHIEVEMENT.ordinal()] = 3;
}
catch (NoSuchFieldError var1)
{
;
}
}
}
}