Files
CatServer/patches/net/minecraft/network/NetHandlerPlayServer.java.patch
2018-09-08 20:40:31 +08:00

1965 lines
105 KiB
Diff

--- ../src-base/minecraft/net/minecraft/network/NetHandlerPlayServer.java
+++ ../src-work/minecraft/net/minecraft/network/NetHandlerPlayServer.java
@@ -3,13 +3,8 @@
import com.google.common.collect.Lists;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Floats;
-import com.google.common.util.concurrent.Futures;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
import net.minecraft.block.BlockCommandBlock;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
@@ -17,6 +12,7 @@
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.crash.ICrashReportDetail;
import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IJumpingMount;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityItem;
@@ -30,76 +26,22 @@
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
-import net.minecraft.inventory.Container;
-import net.minecraft.inventory.ContainerBeacon;
-import net.minecraft.inventory.ContainerMerchant;
-import net.minecraft.inventory.ContainerRepair;
-import net.minecraft.inventory.EntityEquipmentSlot;
-import net.minecraft.inventory.IInventory;
-import net.minecraft.inventory.Slot;
-import net.minecraft.item.ItemElytra;
+import net.minecraft.inventory.*;
+import net.minecraft.item.*;
import net.minecraft.item.ItemStack;
-import net.minecraft.item.ItemWritableBook;
-import net.minecraft.item.ItemWrittenBook;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.play.INetHandlerPlayServer;
-import net.minecraft.network.play.client.CPacketAnimation;
-import net.minecraft.network.play.client.CPacketChatMessage;
-import net.minecraft.network.play.client.CPacketClickWindow;
-import net.minecraft.network.play.client.CPacketClientSettings;
-import net.minecraft.network.play.client.CPacketClientStatus;
-import net.minecraft.network.play.client.CPacketCloseWindow;
-import net.minecraft.network.play.client.CPacketConfirmTeleport;
-import net.minecraft.network.play.client.CPacketConfirmTransaction;
-import net.minecraft.network.play.client.CPacketCreativeInventoryAction;
-import net.minecraft.network.play.client.CPacketCustomPayload;
-import net.minecraft.network.play.client.CPacketEnchantItem;
-import net.minecraft.network.play.client.CPacketEntityAction;
-import net.minecraft.network.play.client.CPacketHeldItemChange;
-import net.minecraft.network.play.client.CPacketInput;
-import net.minecraft.network.play.client.CPacketKeepAlive;
-import net.minecraft.network.play.client.CPacketPlayer;
-import net.minecraft.network.play.client.CPacketPlayerAbilities;
-import net.minecraft.network.play.client.CPacketPlayerDigging;
-import net.minecraft.network.play.client.CPacketPlayerTryUseItem;
-import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock;
-import net.minecraft.network.play.client.CPacketResourcePackStatus;
-import net.minecraft.network.play.client.CPacketSpectate;
-import net.minecraft.network.play.client.CPacketSteerBoat;
-import net.minecraft.network.play.client.CPacketTabComplete;
-import net.minecraft.network.play.client.CPacketUpdateSign;
-import net.minecraft.network.play.client.CPacketUseEntity;
-import net.minecraft.network.play.client.CPacketVehicleMove;
-import net.minecraft.network.play.server.SPacketBlockChange;
-import net.minecraft.network.play.server.SPacketChat;
-import net.minecraft.network.play.server.SPacketConfirmTransaction;
-import net.minecraft.network.play.server.SPacketDisconnect;
-import net.minecraft.network.play.server.SPacketHeldItemChange;
-import net.minecraft.network.play.server.SPacketKeepAlive;
-import net.minecraft.network.play.server.SPacketMoveVehicle;
-import net.minecraft.network.play.server.SPacketPlayerPosLook;
-import net.minecraft.network.play.server.SPacketRespawn;
-import net.minecraft.network.play.server.SPacketSetSlot;
-import net.minecraft.network.play.server.SPacketTabComplete;
+import net.minecraft.network.play.client.*;
+import net.minecraft.network.play.server.*;
import net.minecraft.server.MinecraftServer;
import net.minecraft.stats.AchievementList;
-import net.minecraft.tileentity.CommandBlockBaseLogic;
-import net.minecraft.tileentity.TileEntity;
-import net.minecraft.tileentity.TileEntityCommandBlock;
-import net.minecraft.tileentity.TileEntitySign;
-import net.minecraft.tileentity.TileEntityStructure;
-import net.minecraft.util.ChatAllowedCharacters;
-import net.minecraft.util.EnumFacing;
-import net.minecraft.util.EnumHand;
-import net.minecraft.util.ITickable;
-import net.minecraft.util.IntHashMap;
-import net.minecraft.util.Mirror;
-import net.minecraft.util.ReportedException;
-import net.minecraft.util.Rotation;
+import net.minecraft.tileentity.*;
+import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
@@ -107,10 +49,48 @@
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.GameType;
import net.minecraft.world.WorldServer;
+import net.minecraftforge.fml.common.FMLCommonHandler;
+import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.command.CommandException;
+import org.bukkit.craftbukkit.block.CraftSign;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.util.CraftChatMessage;
+import org.bukkit.craftbukkit.util.LazyPlayerSet;
+import org.bukkit.craftbukkit.util.Waitable;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.block.SignChangeEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.*;
+import org.bukkit.event.player.*;
+import org.bukkit.inventory.*;
+import org.bukkit.util.NumberConversions;
+import org.bukkit.util.Vector;
+import org.spigotmc.SpigotConfig;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import java.util.logging.Level;
+
+//import com.google.common.util.concurrent.Futures;
+//CraftBukkit start
+// CraftBukkit end
+
public class NetHandlerPlayServer implements INetHandlerPlayServer, ITickable
{
private static final Logger LOGGER = LogManager.getLogger();
@@ -121,9 +101,13 @@
private int keepAliveId;
private long lastPingTime;
private long lastSentPingPacket;
- private int chatSpamThresholdCount;
+ //private int chatSpamThresholdCount;
+ // CraftBukkit start - multithreaded fields
+ private volatile int chatSpamThresholdCount;
+ private static AtomicIntegerFieldUpdater<NetHandlerPlayServer> chatSpamField;
+ // CraftBukkit end
private int itemDropThreshold;
- private final IntHashMap<Short> pendingTransactions = new IntHashMap();
+ private final IntHashMap<Short> pendingTransactions = new IntHashMap<Short>();
private double firstGoodX;
private double firstGoodY;
private double firstGoodZ;
@@ -146,7 +130,21 @@
private int vehicleFloatingTickCount;
private int movePacketCounter;
private int lastMovePacketCounter;
+ private boolean processedDisconnect; // CraftBukkit - Added
+ static { // Svarka
+ Field[] fileds = NetHandlerPlayServer.class.getDeclaredFields();
+ for(Field f : fileds) {
+ String n = f.getName();
+ if(n.equals("chatSpamThresholdCount") || n.equals("field_147374_l") || n.equals("i")) {
+ chatSpamField = AtomicIntegerFieldUpdater.newUpdater(NetHandlerPlayServer.class, n);
+ break;
+ }
+ }
+ assert chatSpamField != null;
+ }
+ private boolean placeResult = true; // Svarka check place block
+
public NetHandlerPlayServer(MinecraftServer server, NetworkManager networkManagerIn, EntityPlayerMP playerIn)
{
this.serverController = server;
@@ -154,8 +152,34 @@
networkManagerIn.setNetHandler(this);
this.playerEntity = playerIn;
playerIn.connection = this;
+ // CraftBukkit start - add fields and methods
+ this.server = server.server;
}
+ private final org.bukkit.craftbukkit.CraftServer server;
+ private int lastTick = MinecraftServer.currentTick;
+ private int allowedPlayerTicks = 1;
+ private int lastDropTick = MinecraftServer.currentTick;
+ private int dropCount = 0;
+ private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6;
+ private static final int CREATIVE_PLACE_DISTANCE_SQUARED = 7 * 7;
+
+ // Get position of last block hit for BlockDamageLevel.STOPPED
+ private double lastPosX = Double.MAX_VALUE;
+ private double lastPosY = Double.MAX_VALUE;
+ private double lastPosZ = Double.MAX_VALUE;
+ private float lastPitch = Float.MAX_VALUE;
+ private float lastYaw = Float.MAX_VALUE;
+ private boolean justTeleported = false;
+ // For the PacketPlayOutBlockPlace hack :(
+ Long lastPacket;
+
+ public CraftPlayer getPlayer() {
+ return (this.playerEntity == null) ? null : (CraftPlayer) this.playerEntity.getBukkitEntity();
+ }
+ private final static HashSet<Integer> invalidItems = new HashSet<Integer>(java.util.Arrays.asList(8, 9, 10, 11, 26, 34, 36, 43, 51, 52, 55, 59, 60, 62, 63, 64, 68, 71, 74, 75, 83, 90, 92, 93, 94, 104, 105, 115, 117, 118, 119, 125, 127, 132, 140, 141, 142, 144)); // TODO: Check after every update.
+ // CraftBukkit end
+
public void update()
{
this.captureCurrentPosition();
@@ -175,7 +199,7 @@
}
else
{
- this.floating = false;
+ //this.floating = false;
this.floatingTickCount = 0;
}
@@ -224,11 +248,14 @@
this.serverController.theProfiler.endSection();
+ // CraftBukkit start
+ for (int spam; (spam = this.chatSpamThresholdCount) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ;
+ /*
if (this.chatSpamThresholdCount > 0)
{
--this.chatSpamThresholdCount;
- }
-
+ }*/
+ // CraftBukkit end
if (this.itemDropThreshold > 0)
{
--this.itemDropThreshold;
@@ -236,6 +263,7 @@
if (this.playerEntity.getLastActiveTime() > 0L && this.serverController.getMaxPlayerIdleMinutes() > 0 && MinecraftServer.getCurrentTimeMillis() - this.playerEntity.getLastActiveTime() > (long)(this.serverController.getMaxPlayerIdleMinutes() * 1000 * 60))
{
+ this.playerEntity.markPlayerActive(); // CraftBukkit - SPIGOT-854
this.kickPlayerFromServer("You have been idle for too long!");
}
}
@@ -257,6 +285,25 @@
public void kickPlayerFromServer(String reason)
{
+ // CraftBukkit start - fire PlayerKickEvent
+ if (this.processedDisconnect) {
+ return;
+ }
+ String leaveMessage = TextFormatting.YELLOW + this.playerEntity.getName() + " left the game.";
+
+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.playerEntity), reason, leaveMessage);
+
+ if (this.server.getServer().isServerRunning()) {
+ this.server.getPluginManager().callEvent(event);
+ }
+
+ if (event.isCancelled()) {
+ // Do not kick the player
+ return;
+ }
+ // Send the possibly modified leave message
+ reason = event.getReason();
+ // CraftBukkit end
final TextComponentString textcomponentstring = new TextComponentString(reason);
this.netManager.sendPacket(new SPacketDisconnect(textcomponentstring), new GenericFutureListener < Future <? super Void >> ()
{
@@ -265,9 +312,10 @@
NetHandlerPlayServer.this.netManager.closeChannel(textcomponentstring);
}
}, new GenericFutureListener[0]);
+ this.onDisconnect(textcomponentstring); //CB
this.netManager.disableAutoRead();
- Futures.getUnchecked(this.serverController.addScheduledTask(new Runnable()
- {
+ //Futures.getUnchecked(this.serverController.addScheduledTask(new Runnable()
+ this.serverController.addScheduledTask((new Runnable() {
public void run()
{
NetHandlerPlayServer.this.netManager.checkDisconnected();
@@ -320,8 +368,32 @@
double d9 = entity.motionX * entity.motionX + entity.motionY * entity.motionY + entity.motionZ * entity.motionZ;
double d10 = d6 * d6 + d7 * d7 + d8 * d8;
- if (d10 - d9 > 100.0D && (!this.serverController.isSinglePlayer() || !this.serverController.getServerOwner().equals(entity.getName())))
- {
+ // CraftBukkit start - handle custom speeds and skipped ticks
+ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
+ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1);
+ this.lastTick = (int) (System.currentTimeMillis() / 50);
+
+ ++this.movePacketCounter;
+ int i = this.movePacketCounter - this.lastMovePacketCounter; // PAIL: Rename
+ if (i > Math.max(this.allowedPlayerTicks, 5)) {
+ NetHandlerPlayServer.LOGGER.debug(this.playerEntity.getName() + " is sending move packets too frequently (" + i + " packets since last tick)");
+ i = 1;
+ }
+
+ if (d10 > 0) {
+ allowedPlayerTicks -= 1;
+ } else {
+ allowedPlayerTicks = 20;
+ }
+ float speed;
+ if (playerEntity.capabilities.isFlying) {
+ speed = playerEntity.capabilities.flySpeed * 20f;
+ } else {
+ speed = playerEntity.capabilities.walkSpeed * 10f;
+ }
+ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player
+ if (d10 - d9 > Math.max(100, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && (!this.serverController.isSinglePlayer() || !this.serverController.getServerOwner().equals(entity.getName()))) {
+ // CraftBukkit end
LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[] {entity.getName(), this.playerEntity.getName(), Double.valueOf(d6), Double.valueOf(d7), Double.valueOf(d8)});
this.netManager.sendPacket(new SPacketMoveVehicle(entity));
return;
@@ -345,7 +417,7 @@
d10 = d6 * d6 + d7 * d7 + d8 * d8;
boolean flag1 = false;
- if (d10 > 0.0625D)
+ if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) // Spigot
{
flag1 = true;
LOGGER.warn("{} moved wrongly!", new Object[] {entity.getName()});
@@ -386,6 +458,10 @@
this.lastGoodZ = this.targetPos.zCoord;
this.playerEntity.clearInvulnerableDimensionChange();
}
+
+ this.firstGoodX = targetPos.xCoord;
+ this.firstGoodY = targetPos.yCoord;
+ this.firstGoodZ = targetPos.zCoord;
this.targetPos = null;
}
@@ -417,6 +493,7 @@
this.lastPositionUpdate = this.networkTickCount;
this.setPlayerLocation(this.targetPos.xCoord, this.targetPos.yCoord, this.targetPos.zCoord, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
}
+ allowedPlayerTicks = 20; // CB
}
else
{
@@ -426,77 +503,103 @@
{
this.playerEntity.setPositionAndRotation(this.playerEntity.posX, this.playerEntity.posY, this.playerEntity.posZ, packetIn.getYaw(this.playerEntity.rotationYaw), packetIn.getPitch(this.playerEntity.rotationPitch));
this.serverController.getPlayerList().serverUpdateMountedMovingPlayer(this.playerEntity);
+ allowedPlayerTicks = 20; // CB
}
else
{
- double d0 = this.playerEntity.posX;
- double d1 = this.playerEntity.posY;
- double d2 = this.playerEntity.posZ;
- double d3 = this.playerEntity.posY;
- double d4 = packetIn.getX(this.playerEntity.posX);
- double d5 = packetIn.getY(this.playerEntity.posY);
- double d6 = packetIn.getZ(this.playerEntity.posZ);
- float f = packetIn.getYaw(this.playerEntity.rotationYaw);
- float f1 = packetIn.getPitch(this.playerEntity.rotationPitch);
- double d7 = d4 - this.firstGoodX;
- double d8 = d5 - this.firstGoodY;
- double d9 = d6 - this.firstGoodZ;
+ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify
+ double prevX = playerEntity.posX;
+ double prevY = playerEntity.posY;
+ double prevZ = playerEntity.posZ;
+ float prevYaw = playerEntity.rotationYaw;
+ float prevPitch = playerEntity.rotationPitch;
+ // CraftBukkit end
+ double xprevv = this.playerEntity.posX;
+ double yprevv = this.playerEntity.posY;
+ double zprevv = this.playerEntity.posZ;
+ double y2 = this.playerEntity.posY;
+ double px = packetIn.getX(this.playerEntity.posX);
+ double py = packetIn.getY(this.playerEntity.posY);
+ double pz = packetIn.getZ(this.playerEntity.posZ);
+ float pyaw = packetIn.getYaw(this.playerEntity.rotationYaw);
+ float ppitch = packetIn.getPitch(this.playerEntity.rotationPitch);
+ double mx = px - this.firstGoodX;
+ double my = py - this.firstGoodY;
+ double mz = pz - this.firstGoodZ;
double d10 = this.playerEntity.motionX * this.playerEntity.motionX + this.playerEntity.motionY * this.playerEntity.motionY + this.playerEntity.motionZ * this.playerEntity.motionZ;
- double d11 = d7 * d7 + d8 * d8 + d9 * d9;
+ double moveFromLastTick = mx * mx + my * my + mz * mz;
++this.movePacketCounter;
- int i = this.movePacketCounter - this.lastMovePacketCounter;
+ int recPcts = this.movePacketCounter - this.lastMovePacketCounter;
- if (i > 5)
- {
- LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", new Object[] {this.playerEntity.getName(), Integer.valueOf(i)});
- i = 1;
- }
+ //if (i > 5)
+ //{
+ // LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", new Object[] {this.playerEntity.getName(), Integer.valueOf(i)});
+ // CraftBukkit start - handle custom speeds and skipped ticks
+ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
+ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1);
+ this.lastTick = (int) (System.currentTimeMillis() / 50);
+ if (recPcts > Math.max(this.allowedPlayerTicks, 5)) {
+ recPcts = 1;
+ }
+
+ if (packetIn.rotating || moveFromLastTick > 0) {
+ allowedPlayerTicks -= 1;
+ } else {
+ allowedPlayerTicks = 20;
+ }
+ float speed;
+ if (playerEntity.capabilities.isFlying) {
+ speed = playerEntity.capabilities.flySpeed * 20f;
+ } else {
+ speed = playerEntity.capabilities.walkSpeed * 10f;
+ }
if (!this.playerEntity.isInvulnerableDimensionChange() && (!this.playerEntity.getServerWorld().getGameRules().getBoolean("disableElytraMovementCheck") || !this.playerEntity.isElytraFlying()))
{
float f2 = this.playerEntity.isElytraFlying() ? 300.0F : 100.0F;
- if (d11 - d10 > (double)(f2 * (float)i) && (!this.serverController.isSinglePlayer() || !this.serverController.getServerOwner().equals(this.playerEntity.getName())))
+ if (moveFromLastTick - d10 > /*(double)(f2 * (float)i)*/Math.max(100, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) recPcts * speed), 2)) && (!this.serverController.isSinglePlayer() || !this.serverController.getServerOwner().equals(this.playerEntity.getName())))
{
- LOGGER.warn("{} moved too quickly! {},{},{}", new Object[] {this.playerEntity.getName(), Double.valueOf(d7), Double.valueOf(d8), Double.valueOf(d9)});
+ // CB end
+ LOGGER.warn("{} moved too quickly! {},{},{}", new Object[] {this.playerEntity.getName(), Double.valueOf(mx), Double.valueOf(my), Double.valueOf(mz)});
this.setPlayerLocation(this.playerEntity.posX, this.playerEntity.posY, this.playerEntity.posZ, this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
return;
}
}
boolean flag2 = worldserver.getCollisionBoxes(this.playerEntity, this.playerEntity.getEntityBoundingBox().contract(0.0625D)).isEmpty();
- d7 = d4 - this.lastGoodX;
- d8 = d5 - this.lastGoodY;
- d9 = d6 - this.lastGoodZ;
+ mx = px - this.lastGoodX;
+ my = py - this.lastGoodY;
+ mz = pz - this.lastGoodZ;
- if (this.playerEntity.onGround && !packetIn.isOnGround() && d8 > 0.0D)
+ if (this.playerEntity.onGround && !packetIn.isOnGround() && my > 0.0D)
{
this.playerEntity.jump();
}
- this.playerEntity.moveEntity(d7, d8, d9);
+ this.playerEntity.moveEntity(mx, my, mz);
this.playerEntity.onGround = packetIn.isOnGround();
- double d12 = d8;
- d7 = d4 - this.playerEntity.posX;
- d8 = d5 - this.playerEntity.posY;
+ double d12 = my;
+ mx = px - this.playerEntity.posX;
+ my = py - this.playerEntity.posY;
+ mz = pz - this.playerEntity.posZ;
- if (d8 > -0.5D || d8 < 0.5D)
+ if (my > -0.5D || my < 0.5D)
{
- d8 = 0.0D;
+ my = 0.0D;
}
- d9 = d6 - this.playerEntity.posZ;
- d11 = d7 * d7 + d8 * d8 + d9 * d9;
+ moveFromLastTick = mx * mx + my * my + mz * mz;
boolean flag = false;
- if (!this.playerEntity.isInvulnerableDimensionChange() && d11 > 0.0625D && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.interactionManager.isCreative() && this.playerEntity.interactionManager.getGameType() != GameType.SPECTATOR)
+ if (!this.playerEntity.isInvulnerableDimensionChange() && moveFromLastTick > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.playerEntity.isPlayerSleeping() && !this.playerEntity.interactionManager.isCreative() && this.playerEntity.interactionManager.getGameType() != GameType.SPECTATOR) // Spigot
{
flag = true;
LOGGER.warn("{} moved wrongly!", new Object[] {this.playerEntity.getName()});
}
- this.playerEntity.setPositionAndRotation(d4, d5, d6, f, f1);
- this.playerEntity.addMovementStat(this.playerEntity.posX - d0, this.playerEntity.posY - d1, this.playerEntity.posZ - d2);
+ this.playerEntity.setPositionAndRotation(px, py, pz, pyaw, ppitch);
+ this.playerEntity.addMovementStat(this.playerEntity.posX - xprevv, this.playerEntity.posY - yprevv, this.playerEntity.posZ - zprevv);
if (!this.playerEntity.noClip && !this.playerEntity.isPlayerSleeping())
{
@@ -504,17 +607,80 @@
if (flag2 && (flag || !flag1))
{
- this.setPlayerLocation(d0, d1, d2, f, f1);
+ this.setPlayerLocation(xprevv, yprevv, zprevv, pyaw, ppitch);
return;
}
}
+
+ // CraftBukkit start - fire PlayerMoveEvent
+ // Rest to old location first
+ this.playerEntity.setLocationAndAngles(prevX, prevY, prevZ, prevYaw, prevPitch);
+ Player player = this.getPlayer();
+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location.
+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
+
+ // If the packet contains movement information then we update the To location with the correct XYZ.
+ if (packetIn.moving) {
+ to.setX(packetIn.x);
+ to.setY(packetIn.y);
+ to.setZ(packetIn.z);
+ }
+
+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch.
+ if (packetIn.rotating) {
+ to.setYaw(packetIn.yaw);
+ to.setPitch(packetIn.pitch);
+ }
+
+ // Prevent 40 event-calls for less than a single pixel of movement >.>
+ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2);
+ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch());
+
+ if ((delta > 1f / 256F || deltaAngle > 5f) && !this.playerEntity.isMovementBlockedCB()) {
+ this.lastPosX = to.getX();
+ this.lastPosY = to.getY();
+ this.lastPosZ = to.getZ();
+ this.lastYaw = to.getYaw();
+ this.lastPitch = to.getPitch();
+
+ // Skip the first time we do this
+ if (from.getX() != Double.MAX_VALUE) {
+ Location oldTo = to.clone();
+ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
+ this.server.getPluginManager().callEvent(event);
+
+ // If the event is cancelled we move the player back to their old location.
+ if (event.isCancelled()) {
+ teleport(from);
+ return;
+ }
+
+ // If a Plugin has changed the To destination then we teleport the Player
+ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors.
+ // We only do this if the Event was not cancelled.
+ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) {
+ this.playerEntity.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ return;
+ }
+
+ // Check to see if the Players Location has some how changed during the call of the event.
+ // This can happen due to a plugin teleporting the player instead of using .setTo()
+ if (!from.equals(this.getPlayer().getLocation()) && this.justTeleported) {
+ this.justTeleported = false;
+ return;
+ }
+ }
+ }
+ this.playerEntity.setLocationAndAngles(px, py, pz, pyaw, ppitch); // Copied from above
+ // CraftBukkit end
+
this.floating = d12 >= -0.03125D;
this.floating &= !this.serverController.isFlightAllowed() && !this.playerEntity.capabilities.allowFlying;
this.floating &= !this.playerEntity.isPotionActive(MobEffects.LEVITATION) && !this.playerEntity.isElytraFlying() && !worldserver.checkBlockCollision(this.playerEntity.getEntityBoundingBox().expandXyz(0.0625D).addCoord(0.0D, -0.55D, 0.0D));
this.playerEntity.onGround = packetIn.isOnGround();
this.serverController.getPlayerList().serverUpdateMountedMovingPlayer(this.playerEntity);
- this.playerEntity.handleFalling(this.playerEntity.posY - d3, packetIn.isOnGround());
+ this.playerEntity.handleFalling(this.playerEntity.posY - y2, packetIn.isOnGround());
this.lastGoodX = this.playerEntity.posX;
this.lastGoodY = this.playerEntity.posY;
this.lastGoodZ = this.playerEntity.posZ;
@@ -531,31 +697,99 @@
public void setPlayerLocation(double x, double y, double z, float yaw, float pitch, Set<SPacketPlayerPosLook.EnumFlags> relativeSet)
{
- double d0 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.X) ? this.playerEntity.posX : 0.0D;
- double d1 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Y) ? this.playerEntity.posY : 0.0D;
- double d2 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Z) ? this.playerEntity.posZ : 0.0D;
- this.targetPos = new Vec3d(x + d0, y + d1, z + d2);
+ //double d0 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.X) ? this.playerEntity.posX : 0.0D;
+ //double d1 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Y) ? this.playerEntity.posY : 0.0D;
+ //double d2 = relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Z) ? this.playerEntity.posZ : 0.0D;
+ final Player player = this.getPlayer();
+ final Location from = player.getLocation();
+ double x2 = x;
+ double y2 = y;
+ double z2 = z;
+ //this.targetPos = new Vec3d(x + d0, y + d1, z + d2);
float f = yaw;
float f1 = pitch;
- if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Y_ROT))
- {
- f = yaw + this.playerEntity.rotationYaw;
+ if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.X)) {
+ x2 += from.getX();
}
-
+ if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Y)) {
+ y2 += from.getY();
+ }
+ if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Z)) {
+ z2 += from.getZ();
+ }
+ if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.Y_ROT)) {
+ f += from.getYaw();
+ }
if (relativeSet.contains(SPacketPlayerPosLook.EnumFlags.X_ROT))
{
- f1 = pitch + this.playerEntity.rotationPitch;
+ f1 = from.getPitch();
}
+ Location to = new Location(this.getPlayer().getWorld(), x2, y2, z2, f, f1);
+ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), PlayerTeleportEvent.TeleportCause.UNKNOWN);
+ this.server.getPluginManager().callEvent(event);
+
+ if (event.isCancelled() || !to.equals(event.getTo())) {
+ relativeSet.clear(); // Can't relative teleport
+ to = event.isCancelled() ? event.getFrom() : event.getTo();
+ x = to.getX();
+ y = to.getY();
+ z = to.getZ();
+ yaw = to.getYaw();
+ pitch = to.getPitch();
+ }
+
+ this.internalTeleport(x, y, z, yaw, pitch, relativeSet);
+ //if (++this.teleportId == Integer.MAX_VALUE)
+ //{
+ // this.teleportId = 0;
+ //}
- if (++this.teleportId == Integer.MAX_VALUE)
- {
+ //this.lastPositionUpdate = this.networkTickCount;
+ //this.playerEntity.setPositionAndRotation(this.targetPos.xCoord, this.targetPos.yCoord, this.targetPos.zCoord, f, f1);
+ //this.playerEntity.connection.sendPacket(new SPacketPlayerPosLook(x, y, z, yaw, pitch, relativeSet, this.teleportId));
+ }
+ public void teleport(Location dest) {
+ internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.<SPacketPlayerPosLook.EnumFlags>emptySet());
+ }
+
+ private void internalTeleport(double x, double y, double z, float yaw, float pitch, Set<SPacketPlayerPosLook.EnumFlags> set) {
+ if (Float.isNaN(yaw)) {
+ yaw = 0.0f;
+ }
+ if (Float.isNaN(pitch)) {
+ pitch = 0.0f;
+ }
+ this.justTeleported = true;
+ this.targetPos = new Vec3d(x, y, z);
+ if (set.contains(SPacketPlayerPosLook.EnumFlags.X)) {
+ this.targetPos = this.targetPos.addVector(this.playerEntity.posX, 0.0, 0.0);
+ }
+ if (set.contains(SPacketPlayerPosLook.EnumFlags.Y)) {
+ this.targetPos = this.targetPos.addVector(0.0, this.playerEntity.posY, 0.0);
+ }
+ if (set.contains(SPacketPlayerPosLook.EnumFlags.Z)) {
+ this.targetPos = this.targetPos.addVector(0.0, 0.0, this.playerEntity.posZ);
+ }
+ float f2 = yaw;
+ float f3 = pitch;
+ if (set.contains(SPacketPlayerPosLook.EnumFlags.Y_ROT)) {
+ f2 = yaw + this.playerEntity.rotationYaw;
+ }
+ if (set.contains(SPacketPlayerPosLook.EnumFlags.X_ROT)) {
+ f3 = pitch + this.playerEntity.rotationPitch;
+ }
+ this.lastPosX = this.targetPos.xCoord;
+ this.lastPosY = this.targetPos.yCoord;
+ this.lastPosZ = this.targetPos.zCoord;
+ this.lastYaw = f2;
+ this.lastPitch = f3;
+ if (++this.teleportId == Integer.MAX_VALUE) {
this.teleportId = 0;
}
-
this.lastPositionUpdate = this.networkTickCount;
- this.playerEntity.setPositionAndRotation(this.targetPos.xCoord, this.targetPos.yCoord, this.targetPos.zCoord, f, f1);
- this.playerEntity.connection.sendPacket(new SPacketPlayerPosLook(x, y, z, yaw, pitch, relativeSet, this.teleportId));
+ this.playerEntity.setPositionAndRotation(this.targetPos.xCoord, this.targetPos.yCoord, this.targetPos.zCoord, f2, f3);
+ this.playerEntity.connection.sendPacket(new SPacketPlayerPosLook(x, y, z, yaw, pitch, set, this.teleportId));
}
public void processPlayerDigging(CPacketPlayerDigging packetIn)
@@ -571,9 +805,16 @@
if (!this.playerEntity.isSpectator())
{
- ItemStack itemstack1 = this.playerEntity.getHeldItem(EnumHand.OFF_HAND);
+ // CraftBukkit start
+ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getPlayer(), CraftItemStack.asBukkitCopy(this.playerEntity.getHeldItem(EnumHand.OFF_HAND)), CraftItemStack.asBukkitCopy(this.playerEntity.getHeldItem(EnumHand.MAIN_HAND)));
+ this.server.getPluginManager().callEvent(swapItemsEvent);
+ if (swapItemsEvent.isCancelled()) {
+ return;
+ }
+ ItemStack itemstack1 = CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem());
this.playerEntity.setHeldItem(EnumHand.OFF_HAND, this.playerEntity.getHeldItem(EnumHand.MAIN_HAND));
this.playerEntity.setHeldItem(EnumHand.MAIN_HAND, itemstack1);
+ // CraftBukkit end
}
return;
@@ -632,7 +873,15 @@
}
else
{
+ // CraftBukkit start - fire PlayerInteractEvent
+ CraftEventFactory.callPlayerInteractEvent(this.playerEntity, Action.LEFT_CLICK_BLOCK, blockpos, packetIn.getFacing(), this.playerEntity.inventory.getCurrentItem(), EnumHand.MAIN_HAND);
this.playerEntity.connection.sendPacket(new SPacketBlockChange(worldserver, blockpos));
+ // Update any tile entity data for this block
+ TileEntity tileentity = worldserver.getTileEntity(blockpos);
+ if (tileentity != null) {
+ this.playerEntity.connection.sendPacket(tileentity.getUpdatePacket());
+ }
+ // CraftBukkit end
}
}
else
@@ -676,6 +925,13 @@
dist *= dist;
if (this.targetPos == null && this.playerEntity.getDistanceSq((double)blockpos.getX() + 0.5D, (double)blockpos.getY() + 0.5D, (double)blockpos.getZ() + 0.5D) < dist && !this.serverController.isBlockProtected(worldserver, blockpos, this.playerEntity) && worldserver.getWorldBorder().contains(blockpos))
{
+ // CraftBukkit start - Check if we can actually do something over this large a distance
+ Location eyeLoc = this.getPlayer().getEyeLocation();
+ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockpos.getX()) + NumberConversions.square(eyeLoc.getY() - blockpos.getY()) + NumberConversions.square(eyeLoc.getZ() - blockpos.getZ());
+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) {
+ return;
+ }
+ // CraftBukkit end
this.playerEntity.interactionManager.processRightClickBlock(this.playerEntity, worldserver, itemstack, enumhand, blockpos, enumfacing, packetIn.getFacingX(), packetIn.getFacingY(), packetIn.getFacingZ());
}
}
@@ -697,6 +953,25 @@
}
}
+ // Spigot start - limit place/interactions
+ private int limitedPackets;
+ private long lastLimitedPacket = -1;
+
+ private boolean checkLimit(long timestamp) {
+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) {
+ return false;
+ }
+
+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) {
+ lastLimitedPacket = timestamp;
+ limitedPackets = 0;
+ return true;
+ }
+
+ return true;
+ }
+ // Spigot end
+
public void processPlayerBlockPlacement(CPacketPlayerTryUseItem packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
@@ -707,7 +982,46 @@
if (itemstack != null)
{
- this.playerEntity.interactionManager.processRightClick(this.playerEntity, worldserver, itemstack, enumhand);
+ // CraftBukkit start
+ // Raytrace to look for 'rogue armswings'
+ float f1 = this.playerEntity.rotationPitch;
+ float f2 = this.playerEntity.rotationYaw;
+ double d0 = this.playerEntity.posX;
+ double d1 = this.playerEntity.posY + (double) this.playerEntity.getEyeHeight();
+ double d2 = this.playerEntity.posZ;
+ Vec3d vec3d = new Vec3d(d0, d1, d2);
+
+ float f3 = MathHelper.cos(-f2 * 0.017453292F - 3.1415927F);
+ float f4 = MathHelper.sin(-f2 * 0.017453292F - 3.1415927F);
+ float f5 = -MathHelper.cos(-f1 * 0.017453292F);
+ float f6 = MathHelper.sin(-f1 * 0.017453292F);
+ float f7 = f4 * f5;
+ float f8 = f3 * f5;
+ double d3 = playerEntity.interactionManager.getGameType()== GameType.CREATIVE ? 5.0D : 4.5D;
+ Vec3d vec3d1 = vec3d.addVector((double) f7 * d3, (double) f6 * d3, (double) f8 * d3);
+ RayTraceResult movingobjectposition = this.playerEntity.worldObj.rayTraceBlocks(vec3d, vec3d1, false);
+
+ boolean cancelled;
+ if (movingobjectposition == null || movingobjectposition.typeOfHit != RayTraceResult.Type.BLOCK) {
+ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.playerEntity, Action.RIGHT_CLICK_AIR, itemstack, enumhand);
+ cancelled = event.useItemInHand() == Event.Result.DENY;
+ } else {
+ if (playerEntity.interactionManager.firedInteract) {
+ playerEntity.interactionManager.firedInteract = false;
+ cancelled = playerEntity.interactionManager.interactResult;
+ } else {
+ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(playerEntity, Action.RIGHT_CLICK_BLOCK, movingobjectposition.getBlockPos(), movingobjectposition.sideHit, itemstack, true, enumhand);
+ cancelled = event.useItemInHand() == Event.Result.DENY;
+ }
+ }
+
+ if (cancelled) {
+ this.playerEntity.getBukkitEntity().updateInventory(); // SPIGOT-2524
+ } else {
+ this.playerEntity.interactionManager.processRightClick(this.playerEntity, worldserver, itemstack, enumhand);
+ }
+ // CraftBukkit end
+
itemstack = this.playerEntity.getHeldItem(enumhand);
if (itemstack != null && itemstack.stackSize == 0)
@@ -745,6 +1059,7 @@
this.playerEntity.setSpectatingEntity(this.playerEntity);
this.playerEntity.dismountRidingEntity();
+ /* CraftBukkit start - replace with bukkit handling for multi-world
if (entity.worldObj == this.playerEntity.worldObj)
{
this.playerEntity.setPositionAndUpdate(entity.posX, entity.posY, entity.posZ);
@@ -774,12 +1089,16 @@
this.serverController.getPlayerList().updateTimeAndWeatherForPlayer(this.playerEntity, worldserver2);
this.serverController.getPlayerList().syncPlayerInventory(this.playerEntity);
}
+ */
+ this.playerEntity.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE);
+ // CraftBukkit end
}
}
}
public void handleResourcePackStatus(CPacketResourcePackStatus packetIn)
- {
+ { // CB
+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetIn.action.ordinal()]));
}
public void processSteerBoat(CPacketSteerBoat packetIn)
@@ -795,14 +1114,26 @@
public void onDisconnect(ITextComponent reason)
{
- LOGGER.info("{} lost connection: {}", new Object[] {this.playerEntity.getName(), reason});
+ // CraftBukkit start - Rarely it would send a disconnect line twice
+ if (this.processedDisconnect) {
+ return;
+ } else {
+ this.processedDisconnect = true;
+ }
+ NetHandlerPlayServer.LOGGER.info("{} lost connection: {}", new Object[] { this.playerEntity.getName(), reason.getUnformattedText() });
this.serverController.refreshStatusNextTick();
+ /*LOGGER.info("{} lost connection: {}", new Object[] {this.playerEntity.getName(), reason});
TextComponentTranslation textcomponenttranslation = new TextComponentTranslation("multiplayer.player.left", new Object[] {this.playerEntity.getDisplayName()});
textcomponenttranslation.getStyle().setColor(TextFormatting.YELLOW);
this.serverController.getPlayerList().sendChatMsg(textcomponenttranslation);
+ */
this.playerEntity.mountEntityAndWakeUp();
- this.serverController.getPlayerList().playerLoggedOut(this.playerEntity);
-
+ //this.serverController.getPlayerList().playerLoggedOut(this.playerEntity);
+ final String quitMessage = this.serverController.getPlayerList().playerLoggedOut(this.playerEntity);
+ if (quitMessage != null && quitMessage.length() > 0) {
+ this.serverController.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage));
+ }
+ // CB end
if (this.serverController.isSinglePlayer() && this.playerEntity.getName().equals(this.serverController.getServerOwner()))
{
LOGGER.info("Stopping singleplayer server as player logged out");
@@ -850,23 +1181,37 @@
public void processHeldItemChange(CPacketHeldItemChange packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
-
+ if (this.playerEntity.isDead) return; // CraftBukkit
if (packetIn.getSlotId() >= 0 && packetIn.getSlotId() < InventoryPlayer.getHotbarSize())
{
+ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.playerEntity.inventory.currentItem, packetIn.getSlotId());
+ this.server.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ this.sendPacket(new SPacketHeldItemChange(this.playerEntity.inventory.currentItem));
+ this.playerEntity.markPlayerActive();
+ return;
+ }
+ // CraftBukkit end
this.playerEntity.inventory.currentItem = packetIn.getSlotId();
this.playerEntity.markPlayerActive();
}
else
{
LOGGER.warn("{} tried to set an invalid carried item", new Object[] {this.playerEntity.getName()});
+ this.kickPlayerFromServer("Nope!"); // CraftBukkit
}
}
public void processChatMessage(CPacketChatMessage packetIn)
{
- PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ //PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ // CraftBukkit start - async chat
+ boolean isSync = packetIn.getMessage().startsWith("/");
+ if (isSync) {
+ PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ }
- if (this.playerEntity.getChatVisibility() == EntityPlayer.EnumChatVisibility.HIDDEN)
+ if (this.playerEntity.isDead || this.playerEntity.getChatVisibility() == EntityPlayer.EnumChatVisibility.HIDDEN)
{
TextComponentTranslation textcomponenttranslation = new TextComponentTranslation("chat.cannotSend", new Object[0]);
textcomponenttranslation.getStyle().setColor(TextFormatting.RED);
@@ -882,47 +1227,281 @@
{
if (!ChatAllowedCharacters.isAllowedCharacter(s.charAt(i)))
{
- this.kickPlayerFromServer("Illegal characters in chat");
+ //this.kickPlayerFromServer("Illegal characters in chat");
+ // CraftBukkit start - threadsafety
+ if (!isSync) {
+ Waitable<Object> waitable = new Waitable<Object>() {
+ @Override
+ protected Object evaluate() {
+ kickPlayerFromServer("Illegal characters in chat");
+ return null;
+ }
+ };
+
+ this.serverController.processQueue.add(waitable);
+
+ try {
+ waitable.get(); // Will wait
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ kickPlayerFromServer("Illegal characters in chat");
+ }
+ // CraftBukkit end
return;
}
}
- if (s.startsWith("/"))
+ if (isSync/*s.startsWith("/")*/)
{
- this.handleSlashCommand(s);
+ //this.handleSlashCommand(s);
+ try {
+ this.serverController.server.playerCommandState = true;
+ this.handleSlashCommand(s);
+ }
+ finally {
+ this.serverController.server.playerCommandState = false;
+ }
+ this.serverController.server.playerCommandState = false;
}
- else
- {
- ITextComponent itextcomponent = new TextComponentTranslation("chat.type.text", this.playerEntity.getDisplayName(), net.minecraftforge.common.ForgeHooks.newChatWithLinks(s));
- itextcomponent = net.minecraftforge.common.ForgeHooks.onServerChatEvent(this, s, itextcomponent);
- if (itextcomponent == null) return;
- this.serverController.getPlayerList().sendChatMsgImpl(itextcomponent, false);
+ else if (s.isEmpty()) {
+ NetHandlerPlayServer.LOGGER.warn(String.valueOf(this.playerEntity.getName()) + " tried to send an empty message");
}
+ else if (this.getPlayer().isConversing()) {
+ this.getPlayer().acceptConversationInput(s);
+ }
+ else if (this.playerEntity.getChatVisibility() == EntityPlayer.EnumChatVisibility.SYSTEM) {
+ final TextComponentTranslation chatmessage2 = new TextComponentTranslation("chat.cannotSend", new Object[0]);
+ chatmessage2.getStyle().setColor(TextFormatting.RED);
+ this.sendPacket(new SPacketChat(chatmessage2));
+ }
+ else if (true){
+ this.chat(s, true);
+ }
+ //else
+ //{ // Dead code.
+ // ITextComponent itextcomponent = new TextComponentTranslation("chat.type.text", this.playerEntity.getDisplayName(), net.minecraftforge.common.ForgeHooks.newChatWithLinks(s));
+ // itextcomponent = net.minecraftforge.common.ForgeHooks.onServerChatEvent(this, s, itextcomponent);
+ // if (itextcomponent == null) return;
+ // this.serverController.getPlayerList().sendChatMsgImpl(itextcomponent, false);
+ //}
- this.chatSpamThresholdCount += 20;
+ /*this.chatSpamThresholdCount += 20;
if (this.chatSpamThresholdCount > 200 && !this.serverController.getPlayerList().canSendCommands(this.playerEntity.getGameProfile()))
{
this.kickPlayerFromServer("disconnect.spam");
+ }*/
+ // Spigot start - spam exclusions
+ boolean counted = true;
+ for (String exclude : org.spigotmc.SpigotConfig.spamExclusions)
+ {
+ if (exclude != null && s.startsWith(exclude))
+ {
+ counted = false;
+ break;
+ }
}
+ // Spigot end
+ if (counted && NetHandlerPlayServer.chatSpamField.addAndGet(this, 20) > 200 && !this.serverController.getPlayerList().canSendCommands(this.playerEntity.getGameProfile())) {
+ if (!isSync) {
+ final Waitable<Object> waitable2 = new Waitable<Object>() {
+ @Override
+ protected Object evaluate() {
+ NetHandlerPlayServer.this.kickPlayerFromServer("disconnect.spam");
+ return null;
+ }
+ };
+ this.serverController.processQueue.add(waitable2);
+ try {
+ waitable2.get();
+ return;
+ }
+ catch (InterruptedException ex2) {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ catch (ExecutionException e2) {
+ throw new RuntimeException(e2);
+ }
+ }
+ this.kickPlayerFromServer("disconnect.spam");
+ }
}
}
-
+ // CraftBukkit start - add method
+ public void chat(String s, final boolean async) {
+ if (s.isEmpty() || this.playerEntity.getChatVisibility() == EntityPlayer.EnumChatVisibility.HIDDEN) {
+ return;
+ }
+ if (!async && s.startsWith("/")) {
+ this.handleSlashCommand(s);
+ }
+ else if (this.playerEntity.getChatVisibility() != EntityPlayer.EnumChatVisibility.SYSTEM) {
+ final Player player = this.getPlayer();
+ final AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.serverController));
+ this.server.getPluginManager().callEvent(event);
+ if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) {
+ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients());
+ queueEvent.setCancelled(event.isCancelled());
+ final Waitable waitable = new Waitable() {
+ @Override
+ protected Object evaluate() {
+ Bukkit.getPluginManager().callEvent(queueEvent);
+ if (queueEvent.isCancelled()) {
+ return null;
+ }
+ final String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage());
+ NetHandlerPlayServer.this.serverController.console.sendMessage(message);
+ if (((LazyPlayerSet)queueEvent.getRecipients()).isLazy()) {
+ for (final Object player : NetHandlerPlayServer.this.serverController.getPlayerList().playerEntityList) {
+ ((EntityPlayerMP)player).sendMessage(CraftChatMessage.fromString(message));
+ }
+ }
+ else {
+ for (final Player player2 : queueEvent.getRecipients()) {
+ player2.sendMessage(message);
+ }
+ }
+ return null;
+ }
+ };
+ if (async) {
+ this.serverController.processQueue.add(waitable);
+ }
+ else {
+ waitable.run();
+ }
+ try {
+ waitable.get();
+ return;
+ }
+ catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ catch (ExecutionException e) {
+ throw new RuntimeException("Exception processing chat event", e.getCause());
+ }
+ }
+ if (event.isCancelled()) {
+ return;
+ }
+ s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
+ this.serverController.console.sendMessage(s);
+ if (((LazyPlayerSet)event.getRecipients()).isLazy()) {
+ for (final Object recipient : this.serverController.getPlayerList().playerEntityList) {
+ ((EntityPlayerMP)recipient).sendMessage(CraftChatMessage.fromString(s));
+ }
+ }
+ else {
+ for (final Player recipient2 : event.getRecipients()) {
+ recipient2.sendMessage(s);
+ }
+ }
+ }
+ }
+ // CraftBukkit end
private void handleSlashCommand(String command)
{
- this.serverController.getCommandManager().executeCommand(this.playerEntity, command);
+ //this.serverController.getCommandManager().executeCommand(this.playerEntity, command);
+ final CraftPlayer player = this.getPlayer();
+ final PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, command, new LazyPlayerSet(this.serverController));
+ this.server.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
+ return;
+ }
+ try {
+ if(SpigotConfig.logCommands){
+ LOGGER.info(event.getPlayer().getName() + " issued server command: " + event.getMessage());
+ }
+ // Cauldron start - handle bukkit/vanilla commands
+ int space = event.getMessage().indexOf(" ");
+ // if bukkit command exists then execute it over vanilla
+ if (this.server.getCommandMap().getCommand(event.getMessage().substring(1, space != -1 ? space : event.getMessage().length())) != null)
+ {
+ this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1));
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
+ return;
+ } else {
+ this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1));
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
+ return;
+ }
+ }
+ catch (CommandException ex) {
+ player.sendMessage(ChatColor.RED + "An internal error occurred while attempting to perform this command");
+ java.util.logging.Logger.getLogger(NetHandlerPlayServer.class.getName()).log(Level.SEVERE, null, ex);
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
+ return;
+ }
}
public void handleAnimation(CPacketAnimation packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if(this.playerEntity.isDead) return; // CraftBukkit
this.playerEntity.markPlayerActive();
+ // CB start
+ final float f1 = this.playerEntity.rotationPitch;
+ final float f2 = this.playerEntity.rotationYaw;
+ final double d0 = this.playerEntity.posX;
+ final double d2 = this.playerEntity.posY + this.playerEntity.getEyeHeight();
+ final double d3 = this.playerEntity.posZ;
+ final Vec3d vec3d = new Vec3d(d0, d2, d3);
+ final float f3 = MathHelper.cos(-f2 * 0.017453292f - 3.1415927f);
+ final float f4 = MathHelper.sin(-f2 * 0.017453292f - 3.1415927f);
+ final float f5 = -MathHelper.cos(-f1 * 0.017453292f);
+ final float f6 = MathHelper.sin(-f1 * 0.017453292f);
+ final float f7 = f4 * f5;
+ final float f8 = f3 * f5;
+ final double d4 = (this.playerEntity.interactionManager.getGameType() == GameType.CREATIVE) ? 5.0 : 4.5;
+ final Vec3d vec3d2 = vec3d.addVector(f7 * d4, f6 * d4, f8 * d4);
+ final RayTraceResult movingobjectposition = this.playerEntity.worldObj.rayTraceBlocks(vec3d, vec3d2, false);
+ if (movingobjectposition == null || movingobjectposition.typeOfHit != RayTraceResult.Type.BLOCK) {
+ CraftEventFactory.callPlayerInteractEvent(this.playerEntity, Action.LEFT_CLICK_AIR, this.playerEntity.inventory.getCurrentItem(), EnumHand.MAIN_HAND);
+ }
+ final PlayerAnimationEvent event = new PlayerAnimationEvent(this.getPlayer());
+ this.server.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+ // CB end
this.playerEntity.swingArm(packetIn.getHand());
}
public void processEntityAction(CPacketEntityAction packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ // CB start
+ if (this.playerEntity.isDead) {
+ return;
+ }
+ switch (packetIn.getAction()) {
+ case START_SNEAKING:
+ case STOP_SNEAKING: {
+ final PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getPlayer(), packetIn.getAction() == CPacketEntityAction.Action.START_SNEAKING);
+ this.server.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+ break;
+ }
+ case START_SPRINTING:
+ case STOP_SPRINTING: {
+ final PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getPlayer(), packetIn.getAction() == CPacketEntityAction.Action.START_SPRINTING);
+ this.server.getPluginManager().callEvent(e2);
+ if (e2.isCancelled()) {
+ return;
+ }
+ break;
+ }
+ }
+ // CB end
this.playerEntity.markPlayerActive();
switch (packetIn.getAction())
@@ -999,8 +1578,16 @@
public void processUseEntity(CPacketUseEntity packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
Entity entity = packetIn.getEntityFromWorld(worldserver);
+ // Spigot Start
+ if ( entity == playerEntity && !playerEntity.isSpectator() )
+ {
+ kickPlayerFromServer("Cannot interact with self!");
+ return;
+ }
+ // Spigot End
this.playerEntity.markPlayerActive();
if (entity != null)
@@ -1012,7 +1599,31 @@
{
d0 = 9.0D;
}
-
+ // CB start
+ final ItemStack itemInHand = this.playerEntity.getHeldItem((packetIn.getHand() == null) ? EnumHand.MAIN_HAND : packetIn.getHand());
+ if (packetIn.getAction() == CPacketUseEntity.Action.INTERACT || packetIn.getAction() == CPacketUseEntity.Action.INTERACT_AT) {
+ final boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityLiving;
+ final Item origItem = (this.playerEntity.inventory.getCurrentItem() == null) ? null : this.playerEntity.inventory.getCurrentItem().getItem();
+ PlayerInteractEntityEvent event;
+ if (packetIn.getAction() == CPacketUseEntity.Action.INTERACT) {
+ event = new PlayerInteractEntityEvent(this.getPlayer(), entity.getBukkitEntity(), (packetIn.getHand() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND);
+ }
+ else {
+ final Vec3d target = packetIn.getHitVec();
+ event = new PlayerInteractAtEntityEvent(this.getPlayer(), entity.getBukkitEntity(), new Vector(target.xCoord, target.yCoord, target.zCoord), (packetIn.getHand() == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND);
+ }
+ this.server.getPluginManager().callEvent(event);
+ if (triggerLeashUpdate && (event.isCancelled() || this.playerEntity.inventory.getCurrentItem() == null || this.playerEntity.inventory.getCurrentItem().getItem() != Items.LEAD)) {
+ this.sendPacket(new SPacketEntityAttach(entity, ((EntityLiving)entity).getLeashedToEntity()));
+ }
+ if (event.isCancelled() || this.playerEntity.inventory.getCurrentItem() == null || this.playerEntity.inventory.getCurrentItem().getItem() != origItem) {
+ this.sendPacket(new SPacketEntityMetadata(entity.getEntityId(), entity.dataManager, true));
+ }
+ if (event.isCancelled()) {
+ return;
+ }
+ }
+ // CB end
if (this.playerEntity.getDistanceSqToEntity(entity) < d0)
{
if (packetIn.getAction() == CPacketUseEntity.Action.INTERACT)
@@ -1020,6 +1631,11 @@
EnumHand enumhand = packetIn.getHand();
ItemStack itemstack = this.playerEntity.getHeldItem(enumhand);
this.playerEntity.interact(entity, itemstack, enumhand);
+ // CraftBukkit start
+ if (itemInHand != null && itemInHand.stackSize <= -1) {
+ this.playerEntity.sendContainerToPlayer(this.playerEntity.openContainer);
+ }
+ // CraftBukkit end
}
else if (packetIn.getAction() == CPacketUseEntity.Action.INTERACT_AT)
{
@@ -1027,10 +1643,15 @@
ItemStack itemstack1 = this.playerEntity.getHeldItem(enumhand1);
if(net.minecraftforge.common.ForgeHooks.onInteractEntityAt(playerEntity, entity, packetIn.getHitVec(), itemstack1, enumhand1)) return;
entity.applyPlayerInteraction(this.playerEntity, packetIn.getHitVec(), itemstack1, enumhand1);
+ // CraftBukkit start
+ if (itemInHand != null && itemInHand.stackSize <= -1) {
+ this.playerEntity.sendContainerToPlayer(this.playerEntity.openContainer);
+ }
+ // CraftBukkit end
}
else if (packetIn.getAction() == CPacketUseEntity.Action.ATTACK)
{
- if (entity instanceof EntityItem || entity instanceof EntityXPOrb || entity instanceof EntityArrow || entity == this.playerEntity)
+ if (entity instanceof EntityItem || entity instanceof EntityXPOrb || entity instanceof EntityArrow || (entity == this.playerEntity && !this.playerEntity.isSpectator())) // CB
{
this.kickPlayerFromServer("Attempting to attack an invalid entity");
this.serverController.logWarning("Player " + this.playerEntity.getName() + " tried to attack an invalid entity");
@@ -1038,6 +1659,11 @@
}
this.playerEntity.attackTargetEntityWithCurrentItem(entity);
+ // CraftBukkit start
+ if (itemInHand != null && itemInHand.stackSize <= -1) {
+ this.playerEntity.sendContainerToPlayer(this.playerEntity.openContainer);
+ }
+ // CraftBukkit end
}
}
}
@@ -1056,7 +1682,8 @@
if (this.playerEntity.playerConqueredTheEnd)
{
this.playerEntity.playerConqueredTheEnd = false;
- this.playerEntity = this.serverController.getPlayerList().recreatePlayerEntity(this.playerEntity, 0, true);
+ //this.playerEntity = this.serverController.getPlayerList().recreatePlayerEntity(this.playerEntity, 0, true);
+ this.serverController.getPlayerList().changeDimension(this.playerEntity, 0, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management
}
else
{
@@ -1086,18 +1713,43 @@
public void processCloseWindow(CPacketCloseWindow packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
+ try{
+ if(this.playerEntity.openContainer.getBukkitView() != null){
+ CraftEventFactory.handleInventoryCloseEvent(this.playerEntity); // CraftBukkit
+ }
+ }catch (AbstractMethodError e){
+ // Do nothing
+ }
this.playerEntity.closeContainer();
}
public void processClickWindow(CPacketClickWindow packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
this.playerEntity.markPlayerActive();
if (this.playerEntity.openContainer.windowId == packetIn.getWindowId() && this.playerEntity.openContainer.getCanCraft(this.playerEntity))
{
- if (this.playerEntity.isSpectator())
+ final boolean cancelled = this.playerEntity.isSpectator(); // CraftBukkit - see below if
+ final boolean cbInv = this.playerEntity.openContainer instanceof Container;
+ InventoryClickEvent event = null;
+ InventoryView inventory = this.playerEntity.openContainer.getBukkitView();
+ InventoryType.SlotType type = CraftInventoryView.getSlotType(inventory, packetIn.getSlotId());
+ ClickType click = ClickType.UNKNOWN;
+ InventoryAction action = InventoryAction.UNKNOWN;
+
+ // Cauldron start - some containers such as NEI's Creative Container does not have a view at this point so we need to create one
+ if (inventory == null)
{
+ inventory = new CraftInventoryView(this.playerEntity.getBukkitEntity(), MinecraftServer.getServerInst().server.createInventory(this.playerEntity.getBukkitEntity(), InventoryType.CHEST), this.playerEntity.openContainer);
+ this.playerEntity.openContainer.bukkitView = inventory;
+ }
+ // Cauldron end
+
+ if(cancelled && !cbInv)
+ {
List<ItemStack> list = Lists.<ItemStack>newArrayList();
for (int i = 0; i < this.playerEntity.openContainer.inventorySlots.size(); ++i)
@@ -1109,9 +1761,321 @@
}
else
{
- ItemStack itemstack2 = this.playerEntity.openContainer.slotClick(packetIn.getSlotId(), packetIn.getUsedButton(), packetIn.getClickType(), this.playerEntity);
+ ItemStack itemstack = null;
+ if(!cbInv) {
+ itemstack = this.playerEntity.openContainer.slotClick(packetIn.getSlotId(), packetIn.getUsedButton(), packetIn.getClickType(), this.playerEntity);
+ }
+ if (packetIn.getSlotId() < -1 && packetIn.getSlotId() != -999) {
+ return;
+ }
+ if(cbInv) {
- if (ItemStack.areItemStacksEqual(packetIn.getClickedItem(), itemstack2))
+ switch (packetIn.getClickType()) {
+ case PICKUP: {
+ if (packetIn.getUsedButton() == 0) {
+ click = ClickType.LEFT;
+ }
+ else if (packetIn.getUsedButton() == 1) {
+ click = ClickType.RIGHT;
+ }
+ if (packetIn.getUsedButton() != 0 && packetIn.getUsedButton() != 1) {
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ if (packetIn.getSlotId() == -999) {
+ if (this.playerEntity.inventory.getItemStack() != null) {
+ action = ((packetIn.getUsedButton() == 0) ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR);
+ break;
+ }
+ break;
+ }
+ else {
+ if (packetIn.getSlotId() < 0) {
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ final Slot slot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (slot == null) {
+ break;
+ }
+ final ItemStack clickedItem = slot.getStack();
+ final ItemStack cursor = this.playerEntity.inventory.getItemStack();
+ if (clickedItem == null) {
+ if (cursor != null) {
+ action = ((packetIn.getUsedButton() == 0) ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE);
+ break;
+ }
+ break;
+ }
+ else {
+ if (!slot.canTakeStack(this.playerEntity)) {
+ break;
+ }
+ if (cursor == null) {
+ action = ((packetIn.getUsedButton() == 0) ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF);
+ break;
+ }
+ if (slot.isItemValid(cursor)) {
+ if (clickedItem.isItemEqual(cursor) && ItemStack.areItemStackTagsEqual(clickedItem, cursor)) {
+ int toPlace = (packetIn.getUsedButton() == 0) ? cursor.stackSize : 1;
+ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.stackSize);
+ toPlace = Math.min(toPlace, slot.inventory.getInventoryStackLimit() - clickedItem.stackSize);
+ if (toPlace == 1) {
+ action = InventoryAction.PLACE_ONE;
+ break;
+ }
+ if (toPlace == cursor.stackSize) {
+ action = InventoryAction.PLACE_ALL;
+ break;
+ }
+ if (toPlace < 0) {
+ action = ((toPlace != -1) ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE);
+ break;
+ }
+ if (toPlace != 0) {
+ action = InventoryAction.PLACE_SOME;
+ break;
+ }
+ break;
+ }
+ else {
+ if (cursor.stackSize <= slot.getSlotStackLimit()) {
+ action = InventoryAction.SWAP_WITH_CURSOR;
+ break;
+ }
+ break;
+ }
+ }
+ else {
+ if (cursor.getItem() == clickedItem.getItem() && (!cursor.getHasSubtypes() || cursor.getMetadata() == clickedItem.getMetadata()) && ItemStack.areItemStackTagsEqual(cursor, clickedItem) && clickedItem.stackSize >= 0 && clickedItem.stackSize + cursor.stackSize <= cursor.getMaxStackSize()) {
+ action = InventoryAction.PICKUP_ALL;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ //break;
+ }
+ case QUICK_MOVE: {
+ if (packetIn.getUsedButton() == 0) {
+ click = ClickType.SHIFT_LEFT;
+ }
+ else if (packetIn.getUsedButton() == 1) {
+ click = ClickType.SHIFT_RIGHT;
+ }
+ if (packetIn.getUsedButton() != 0 && packetIn.getUsedButton() != 1) {
+ break;
+ }
+ if (packetIn.getSlotId() < 0) {
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ final Slot slot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (slot != null && slot.canTakeStack(this.playerEntity) && slot.getHasStack()) {
+ action = InventoryAction.MOVE_TO_OTHER_INVENTORY;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ // Special constructor for number key
+ event = new InventoryClickEvent(inventory, type, packetIn.getSlotId(), click, action, packetIn.getUsedButton());
+ break;
+ }
+ case SWAP: {
+ if (packetIn.getUsedButton() < 0 || packetIn.getUsedButton() >= 9) {
+ break;
+ }
+ click = ClickType.NUMBER_KEY;
+ final Slot clickedSlot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (!clickedSlot.canTakeStack(this.playerEntity)) {
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ final ItemStack hotbar = this.playerEntity.inventory.getStackInSlot(packetIn.getUsedButton());
+ final boolean canCleanSwap = hotbar == null || (clickedSlot.inventory == this.playerEntity.inventory && clickedSlot.isItemValid(hotbar));
+ if (clickedSlot.getHasStack()) {
+ if (canCleanSwap) {
+ action = InventoryAction.HOTBAR_SWAP;
+ break;
+ }
+ final int firstEmptySlot = this.playerEntity.inventory.getFirstEmptyStack();
+ if (firstEmptySlot > -1) {
+ action = InventoryAction.HOTBAR_MOVE_AND_READD;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ else {
+ if (!clickedSlot.getHasStack() && hotbar != null && clickedSlot.isItemValid(hotbar)) {
+ action = InventoryAction.HOTBAR_SWAP;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ //break;
+ }
+ case CLONE: {
+ if (packetIn.getUsedButton() != 2) {
+ click = ClickType.UNKNOWN;
+ action = InventoryAction.UNKNOWN;
+ break;
+ }
+ click = ClickType.MIDDLE;
+ if (packetIn.getSlotId() == -999) {
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ final Slot slot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (slot != null && slot.getHasStack() && this.playerEntity.capabilities.isCreativeMode && this.playerEntity.inventory.getItemStack() == null) {
+ action = InventoryAction.CLONE_STACK;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ case THROW: {
+ if (packetIn.getSlotId() < 0) {
+ click = ClickType.LEFT;
+ if (packetIn.getUsedButton() == 1) {
+ click = ClickType.RIGHT;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ if (packetIn.getUsedButton() == 0) {
+ click = ClickType.DROP;
+ final Slot slot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (slot != null && slot.getHasStack() && slot.canTakeStack(this.playerEntity) && slot.getStack() != null && slot.getStack().getItem() != Item.getItemFromBlock(Blocks.AIR)) {
+ action = InventoryAction.DROP_ONE_SLOT;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ else {
+ if (packetIn.getUsedButton() != 1) {
+ break;
+ }
+ click = ClickType.CONTROL_DROP;
+ final Slot slot = this.playerEntity.openContainer.getSlot(packetIn.getSlotId());
+ if (slot != null && slot.getHasStack() && slot.canTakeStack(this.playerEntity) && slot.getStack() != null && slot.getStack().getItem() != Item.getItemFromBlock(Blocks.AIR)) {
+ action = InventoryAction.DROP_ALL_SLOT;
+ break;
+ }
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ //break;
+ }
+ case QUICK_CRAFT: {
+ itemstack = this.playerEntity.openContainer.slotClick(packetIn.getSlotId(), packetIn.getUsedButton(), packetIn.getClickType(), this.playerEntity);
+ break;
+ }
+ case PICKUP_ALL: {
+ click = ClickType.DOUBLE_CLICK;
+ action = InventoryAction.NOTHING;
+ if (packetIn.getSlotId() < 0 || this.playerEntity.inventory.getItemStack() == null) {
+ break;
+ }
+ final ItemStack cursor2 = this.playerEntity.inventory.getItemStack();
+ action = InventoryAction.NOTHING;
+ if (inventory.getTopInventory().contains(org.bukkit.Material.getMaterial(Item.getIdFromItem(cursor2.getItem()))) || inventory.getBottomInventory().contains(org.bukkit.Material.getMaterial(Item.getIdFromItem(cursor2.getItem())))) {
+ action = InventoryAction.COLLECT_TO_CURSOR;
+ break;
+ }
+ break;
+ }
+ }
+ if (packetIn.getClickType() != net.minecraft.inventory.ClickType.QUICK_CRAFT) {
+ if (click == ClickType.NUMBER_KEY) {
+ event = new InventoryClickEvent(inventory, type, packetIn.getSlotId(), click, action, packetIn.getUsedButton());
+ } else {
+ event = new InventoryClickEvent(inventory, type, packetIn.getSlotId(), click, action);
+ }
+ final Inventory top = inventory.getTopInventory();
+ if (packetIn.getSlotId() == 0 && top instanceof CraftingInventory) {
+ final Recipe recipe = ((CraftingInventory)top).getRecipe();
+ if (recipe != null) {
+ if (click == ClickType.NUMBER_KEY) {
+ event = new CraftItemEvent(recipe, inventory, type, packetIn.getSlotId(), click, action, packetIn.getUsedButton());
+ }
+ else {
+ event = new CraftItemEvent(recipe, inventory, type, packetIn.getSlotId(), click, action);
+ }
+ }
+ }
+ this.server.getPluginManager().callEvent(event);
+ switch (event.getResult()) {
+ case DEFAULT:
+ case ALLOW: {
+ itemstack = this.playerEntity.openContainer.slotClick(packetIn.getSlotId(), packetIn.getUsedButton(), packetIn.getClickType(), this.playerEntity);
+ break;
+ }
+ case DENY: {
+ switch (action) {
+ case PICKUP_ALL:
+ case MOVE_TO_OTHER_INVENTORY:
+ case HOTBAR_MOVE_AND_READD:
+ case HOTBAR_SWAP:
+ case COLLECT_TO_CURSOR:
+ case UNKNOWN: {
+ this.playerEntity.sendContainerToPlayer(this.playerEntity.openContainer);
+ break;
+ }
+ case PICKUP_SOME:
+ case PICKUP_HALF:
+ case PICKUP_ONE:
+ case PLACE_ALL:
+ case PLACE_SOME:
+ case PLACE_ONE:
+ case SWAP_WITH_CURSOR: {
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(-1, -1, this.playerEntity.inventory.getItemStack()));
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(this.playerEntity.openContainer.windowId, packetIn.getSlotId(), this.playerEntity.openContainer.getSlot(packetIn.getSlotId()).getStack()));
+ break;
+ }
+ case DROP_ALL_SLOT:
+ case DROP_ONE_SLOT: {
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(this.playerEntity.openContainer.windowId, packetIn.getSlotId(), this.playerEntity.openContainer.getSlot(packetIn.getSlotId()).getStack()));
+ break;
+ }
+ case DROP_ALL_CURSOR:
+ case DROP_ONE_CURSOR:
+ case CLONE_STACK: {
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(-1, -1, this.playerEntity.inventory.getItemStack()));
+ break;
+ }
+ }
+ return;
+ }
+ }
+ if (event instanceof CraftItemEvent) {
+ this.playerEntity.sendContainerToPlayer(this.playerEntity.openContainer);
+ }
+ }
+ }
+ if (ItemStack.areItemStacksEqual(packetIn.getClickedItem(), itemstack)) {
+ this.playerEntity.connection.sendPacket(new SPacketConfirmTransaction(packetIn.getWindowId(), packetIn.getActionNumber(), true));
+ this.playerEntity.isChangingQuantityOnly = true;
+ this.playerEntity.openContainer.detectAndSendChanges();
+ this.playerEntity.updateHeldItem();
+ this.playerEntity.isChangingQuantityOnly = false;
+ }
+ else {
+ this.pendingTransactions.addKey(this.playerEntity.openContainer.windowId, packetIn.getActionNumber());
+ this.playerEntity.connection.sendPacket(new SPacketConfirmTransaction(packetIn.getWindowId(), packetIn.getActionNumber(), false));
+ this.playerEntity.openContainer.setCanCraft(this.playerEntity, false);
+ final ArrayList<ItemStack> arraylist1 = Lists.newArrayList();
+ for (int j = 0; j < this.playerEntity.openContainer.inventorySlots.size(); ++j) {
+ final ItemStack itemstack2 = this.playerEntity.openContainer.inventorySlots.get(j).getStack();
+ final ItemStack itemstack3 = (itemstack2 != null && itemstack2.stackSize > 0) ? itemstack2 : null;
+ arraylist1.add(itemstack3);
+ }
+ this.playerEntity.updateCraftingInventory(this.playerEntity.openContainer, arraylist1);
+ }
+
+ if (ItemStack.areItemStacksEqual(packetIn.getClickedItem(), itemstack))
{
this.playerEntity.connection.sendPacket(new SPacketConfirmTransaction(packetIn.getWindowId(), packetIn.getActionNumber(), true));
this.playerEntity.isChangingQuantityOnly = true;
@@ -1128,8 +2092,8 @@
for (int j = 0; j < this.playerEntity.openContainer.inventorySlots.size(); ++j)
{
- ItemStack itemstack = ((Slot)this.playerEntity.openContainer.inventorySlots.get(j)).getStack();
- ItemStack itemstack1 = itemstack != null && itemstack.stackSize > 0 ? itemstack : null;
+ ItemStack itemstack2 = ((Slot)this.playerEntity.openContainer.inventorySlots.get(j)).getStack();
+ ItemStack itemstack1 = itemstack2 != null && itemstack2.stackSize > 0 ? itemstack2 : null;
list1.add(itemstack1);
}
@@ -1142,6 +2106,7 @@
public void processEnchantItem(CPacketEnchantItem packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
this.playerEntity.markPlayerActive();
if (this.playerEntity.openContainer.windowId == packetIn.getWindowId() && this.playerEntity.openContainer.getCanCraft(this.playerEntity) && !this.playerEntity.isSpectator())
@@ -1181,9 +2146,45 @@
}
boolean flag1 = packetIn.getSlotId() >= 1 && packetIn.getSlotId() <= 45;
- boolean flag2 = itemstack == null || itemstack.getItem() != null;
+ // CraftBukkit - Add invalidItems check
+ boolean flag2 = itemstack == null || itemstack.getItem() != null && (!NetHandlerPlayServer.invalidItems.contains(Item.getIdFromItem(itemstack.getItem())) || !org.spigotmc.SpigotConfig.filterCreativeItems); // Spigot
boolean flag3 = itemstack == null || itemstack.getMetadata() >= 0 && itemstack.stackSize <= 64 && itemstack.stackSize > 0;
-
+ // CraftBukkit start - Call click event
+ if (flag || (flag2 && !ItemStack.areItemStacksEqual(this.playerEntity.inventoryContainer.getSlot(packetIn.getSlotId()).getStack(), packetIn.getStack()))) {
+ final HumanEntity player = this.playerEntity.getBukkitEntity();
+ final InventoryView inventory = new CraftInventoryView(player, player.getInventory(), this.playerEntity.inventoryContainer);
+ final org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetIn.getStack());
+ InventoryType.SlotType type = InventoryType.SlotType.QUICKBAR;
+ if (flag) {
+ type = InventoryType.SlotType.OUTSIDE;
+ }
+ else if (packetIn.getSlotId() < 36) {
+ if (packetIn.getSlotId() >= 5 && packetIn.getSlotId() < 9) {
+ type = InventoryType.SlotType.ARMOR;
+ }
+ else {
+ type = InventoryType.SlotType.CONTAINER;
+ }
+ }
+ final InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetIn.getSlotId(), item);
+ this.server.getPluginManager().callEvent(event);
+ itemstack = CraftItemStack.asNMSCopy(event.getCursor());
+ switch (event.getResult()) {
+ case ALLOW: {
+ flag2 = (flag3 = true);
+ }
+ case DENY: {
+ if (packetIn.getSlotId() >= 0) {
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(this.playerEntity.inventoryContainer.windowId, packetIn.getSlotId(), this.playerEntity.inventoryContainer.getSlot(packetIn.getSlotId()).getStack()));
+ this.playerEntity.connection.sendPacket(new SPacketSetSlot(-1, -1, null));
+ }
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ // CB end
if (flag1 && flag2 && flag3)
{
if (itemstack == null)
@@ -1213,6 +2214,7 @@
public void processConfirmTransaction(CPacketConfirmTransaction packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
Short oshort = (Short)this.pendingTransactions.lookup(this.playerEntity.openContainer.windowId);
if (oshort != null && packetIn.getUid() == oshort.shortValue() && this.playerEntity.openContainer.windowId == packetIn.getWindowId() && !this.playerEntity.openContainer.getCanCraft(this.playerEntity) && !this.playerEntity.isSpectator())
@@ -1224,6 +2226,7 @@
public void processUpdateSign(CPacketUpdateSign packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ if (this.playerEntity.isDead) return; // CraftBukkit
this.playerEntity.markPlayerActive();
WorldServer worldserver = this.serverController.worldServerForDimension(this.playerEntity.dimension);
BlockPos blockpos = packetIn.getPosition();
@@ -1243,16 +2246,32 @@
if (!tileentitysign.getIsEditable() || tileentitysign.getPlayer() != this.playerEntity)
{
this.serverController.logWarning("Player " + this.playerEntity.getName() + " just tried to change non-editable sign");
+ this.sendPacket(tileentity.getUpdatePacket());
return;
}
String[] astring = packetIn.getLines();
- for (int i = 0; i < astring.length; ++i)
- {
- tileentitysign.signText[i] = new TextComponentString(TextFormatting.getTextWithoutFormattingCodes(astring[i]));
+ //for (int i = 0; i < astring.length; ++i)
+ //{
+ // tileentitysign.signText[i] = new TextComponentString(TextFormatting.getTextWithoutFormattingCodes(astring[i]));
+ //}
+ // CB start
+ final Player player = this.server.getPlayer(this.playerEntity);
+ final int x = packetIn.getPosition().getX();
+ final int y = packetIn.getPosition().getY();
+ final int z = packetIn.getPosition().getZ();
+ final String[] lines = new String[4];
+ for (int i = 0; i < astring.length; ++i) {
+ lines[i] = TextFormatting.getTextWithoutFormattingCodes(new TextComponentString(TextFormatting.getTextWithoutFormattingCodes(astring[i])).getUnformattedText());
}
-
+ final SignChangeEvent event = new SignChangeEvent(player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.playerEntity), lines);
+ this.server.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ System.arraycopy(CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.signText, 0, 4);
+ tileentitysign.isEditable = false;
+ }
+ // CB end
tileentitysign.markDirty();
worldserver.notifyBlockUpdate(blockpos, iblockstate, iblockstate, 3);
}
@@ -1275,12 +2294,30 @@
public void processPlayerAbilities(CPacketPlayerAbilities packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
- this.playerEntity.capabilities.isFlying = packetIn.isFlying() && this.playerEntity.capabilities.allowFlying;
+ //this.playerEntity.capabilities.isFlying = packetIn.isFlying() && this.playerEntity.capabilities.allowFlying;
+ // CB start
+ if (this.playerEntity.capabilities.allowFlying && this.playerEntity.capabilities.isFlying != packetIn.isFlying()) {
+ final PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.server.getPlayer(this.playerEntity), packetIn.isFlying());
+ this.server.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ this.playerEntity.capabilities.isFlying = packetIn.isFlying();
+ }
+ else {
+ this.playerEntity.sendPlayerAbilities();
+ }
+ }
+ // CB end
}
public void processTabComplete(CPacketTabComplete packetIn)
{
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.playerEntity.getServerWorld());
+ // CB start
+ if (NetHandlerPlayServer.chatSpamField.addAndGet(this, 10) > 500 && !this.serverController.getPlayerList().canSendCommands(this.playerEntity.getGameProfile())) {
+ this.kickPlayerFromServer("disconnect.spam");
+ return;
+ }
+ // CB end
List<String> list = Lists.<String>newArrayList();
for (String s : this.serverController.getTabCompletions(this.playerEntity, packetIn.getMessage(), packetIn.getTargetBlock(), packetIn.hasTargetBlock()))
@@ -1329,12 +2366,15 @@
if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack.getItem() == itemstack1.getItem())
{
+ itemstack1 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit
itemstack1.setTagInfo("pages", itemstack.getTagCompound().getTagList("pages", 8));
+ CraftEventFactory.handleEditBookEvent(playerEntity, itemstack1); // CraftBukkit
}
}
catch (Exception exception6)
{
LOGGER.error((String)"Couldn\'t handle book info", (Throwable)exception6);
+ this.kickPlayerFromServer("Invalid book data!"); // CraftBukkit
}
}
else if ("MC|BSign".equals(s))
@@ -1364,6 +2404,7 @@
if (itemstack2.getItem() == Items.WRITABLE_BOOK && itemstack3.getItem() == Items.WRITABLE_BOOK)
{
+ itemstack3 = new ItemStack(Items.WRITABLE_BOOK); // CraftBukkit
itemstack3.setTagInfo("author", new NBTTagString(this.playerEntity.getName()));
itemstack3.setTagInfo("title", new NBTTagString(itemstack2.getTagCompound().getString("title")));
NBTTagList nbttaglist = itemstack2.getTagCompound().getTagList("pages", 8);
@@ -1378,11 +2419,13 @@
itemstack3.setTagInfo("pages", nbttaglist);
itemstack3.setItem(Items.WRITTEN_BOOK);
+ CraftEventFactory.handleEditBookEvent(playerEntity, itemstack3); // CraftBukkit
}
}
catch (Exception exception7)
{
LOGGER.error((String)"Couldn\'t sign book", (Throwable)exception7);
+ this.kickPlayerFromServer("Invalid book data!"); // CraftBukkit
}
}
else if ("MC|TrSel".equals(s))
@@ -1400,6 +2443,7 @@
catch (Exception exception5)
{
LOGGER.error((String)"Couldn\'t select trade", (Throwable)exception5);
+ this.kickPlayerFromServer("Invalid trade data!"); // CraftBukkit
}
}
else if ("MC|AdvCmd".equals(s))
@@ -1462,6 +2506,7 @@
catch (Exception exception4)
{
LOGGER.error((String)"Couldn\'t set command block", (Throwable)exception4);
+ this.kickPlayerFromServer("Invalid command data!"); // CraftBukkit
}
}
else if ("MC|AutoCmd".equals(s))
@@ -1540,6 +2585,7 @@
catch (Exception exception3)
{
LOGGER.error((String)"Couldn\'t set command block", (Throwable)exception3);
+ this.kickPlayerFromServer("Invalid command data!"); // CraftBukkit
}
}
else if ("MC|Beacon".equals(s))
@@ -1566,6 +2612,7 @@
catch (Exception exception2)
{
LOGGER.error((String)"Couldn\'t set beacon", (Throwable)exception2);
+ this.kickPlayerFromServer("Invalid beacon data!"); // CraftBukkit
}
}
}
@@ -1589,6 +2636,10 @@
containerrepair.updateItemName("");
}
}
+ // Cauldron - bukkit registration moved to FML's ChannelRegistrationHandler
+ else{
+ server.getMessenger().dispatchIncomingMessage(playerEntity.getBukkitEntity(),packetIn.getChannelName(),packetIn.getBufferData().readByteArray());
+ }
}
else if ("MC|Struct".equals(s))
{
@@ -1677,6 +2728,7 @@
catch (Exception exception1)
{
LOGGER.error((String)"Couldn\'t set structure block", (Throwable)exception1);
+ this.kickPlayerFromServer("Invalid structure data!"); // CraftBukkit
}
}
else if ("MC|PickItem".equals(s))
@@ -1694,7 +2746,36 @@
catch (Exception exception)
{
LOGGER.error((String)"Couldn\'t pick item", (Throwable)exception);
+ this.kickPlayerFromServer("Invalid item data!"); // CraftBukkit
}
}
+ // CB start
+ else if (packetIn.getChannelName().equals("REGISTER")) {
+ final String channels = new String(packetIn.getBufferData().array(), Charsets.UTF_8);
+ String[] split;
+ for (int length = (split = channels.split("\0")).length, n = 0; n < length; ++n) {
+ final String channel = split[n];
+ this.getPlayer().addChannel(channel);
+ }
+ }
+ else if (packetIn.getChannelName().equals("UNREGISTER")) {
+ final String channels = new String(packetIn.getBufferData().array(), Charsets.UTF_8);
+ String[] split2;
+ for (int length2 = (split2 = channels.split("\0")).length, n2 = 0; n2 < length2; ++n2) {
+ final String channel = split2[n2];
+ this.getPlayer().removeChannel(channel);
+ }
+ }
+ else {
+ final byte[] data = new byte[packetIn.getBufferData().readableBytes()];
+ packetIn.getBufferData().readBytes(data);
+ this.server.getMessenger().dispatchIncomingMessage(this.playerEntity.getBukkitEntity(), packetIn.getChannelName(), data);
+ }
+ // CB end
}
+
+ // CraftBukkit start - Add "isDisconnected" method
+ public final boolean isDisconnected() {
+ return !playerEntity.joining && !this.netManager.isChannelOpen();
+ }
}