From 0b251c5440ba1a7c56cf207c0df8906146e896a4 Mon Sep 17 00:00:00 2001 From: Sergey Shatunov Date: Sat, 6 Feb 2016 04:29:03 +0700 Subject: [PATCH] Implement ReverseClonner, which should fix all issues with teleportation/inventories/crashed after respawning --- .../entity/player/EntityPlayer.java.patch | 22 ++++++-------- .../entity/player/EntityPlayerMP.java.patch | 11 +------ .../network/NetHandlerPlayServer.java.patch | 13 +++++++-- .../ServerConfigurationManager.java.patch | 29 +++++++++---------- src/main/java/kcauldron/ReverseClonner.java | 24 +++++++++++++++ .../craftbukkit/entity/CraftHumanEntity.java | 9 ------ .../craftbukkit/entity/CraftLivingEntity.java | 13 ++++----- .../craftbukkit/entity/CraftPlayer.java | 5 ++-- .../craftbukkit/inventory/CraftInventory.java | 6 +--- .../inventory/CraftInventoryPlayer.java | 2 +- 10 files changed, 69 insertions(+), 65 deletions(-) create mode 100644 src/main/java/kcauldron/ReverseClonner.java diff --git a/patches/net/minecraft/entity/player/EntityPlayer.java.patch b/patches/net/minecraft/entity/player/EntityPlayer.java.patch index f8f3a67..ed71f50 100644 --- a/patches/net/minecraft/entity/player/EntityPlayer.java.patch +++ b/patches/net/minecraft/entity/player/EntityPlayer.java.patch @@ -23,12 +23,8 @@ public abstract class EntityPlayer extends EntityLivingBase implements ICommandSender { public static final String PERSISTED_NBT_TAG = "PlayerPersisted"; -@@ -99,10 +115,10 @@ - private HashMap spawnForcedMap = new HashMap(); - - public InventoryPlayer inventory = new InventoryPlayer(this); -- private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest(); -+ public InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest(); +@@ -102,7 +118,7 @@ + private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest(); public Container inventoryContainer; public Container openContainer; - protected FoodStats foodStats = new FoodStats(); @@ -503,12 +499,12 @@ } } -@@ -2023,7 +2246,7 @@ - this.setScore(p_71049_1_.getScore()); +@@ -2035,7 +2258,7 @@ + { + getEntityData().setTag(PERSISTED_NBT_TAG, old.getCompoundTag(PERSISTED_NBT_TAG)); } +- MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerEvent.Clone(this, p_71049_1_, !p_71049_2_)); ++ //MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerEvent.Clone(this, p_71049_1_, !p_71049_2_)); // KCauldron - moved to ReverseClonner + } -- this.theInventoryEnderChest = p_71049_1_.theInventoryEnderChest; -+ // this.theInventoryEnderChest = p_71049_1_.theInventoryEnderChest; // KCauldron - moved up - - this.spawnChunkMap = p_71049_1_.spawnChunkMap; - this.spawnForcedMap = p_71049_1_.spawnForcedMap; + protected boolean canTriggerWalking() diff --git a/patches/net/minecraft/entity/player/EntityPlayerMP.java.patch b/patches/net/minecraft/entity/player/EntityPlayerMP.java.patch index 0a758dc..2f72840 100644 --- a/patches/net/minecraft/entity/player/EntityPlayerMP.java.patch +++ b/patches/net/minecraft/entity/player/EntityPlayerMP.java.patch @@ -705,16 +705,7 @@ public void addChatComponentMessage(IChatComponent p_146105_1_) { this.playerNetServerHandler.sendPacket(new S02PacketChat(p_146105_1_)); -@@ -878,6 +1204,8 @@ - - public void clonePlayer(EntityPlayer p_71049_1_, boolean p_71049_2_) - { -+ this.theInventoryEnderChest = p_71049_1_.theInventoryEnderChest; -+ if (p_71049_1_ instanceof EntityPlayerMP) ((org.bukkit.craftbukkit.entity.CraftLivingEntity) (bukkitEntity = ((EntityPlayerMP) p_71049_1_).bukkitEntity)).updateEntity(this); - super.clonePlayer(p_71049_1_, p_71049_2_); - this.lastExperience = -1; - this.lastHealth = -1.0F; -@@ -1037,6 +1365,114 @@ +@@ -1037,6 +1363,114 @@ return this.field_143005_bX; } diff --git a/patches/net/minecraft/network/NetHandlerPlayServer.java.patch b/patches/net/minecraft/network/NetHandlerPlayServer.java.patch index 86b75d8..5af476d 100644 --- a/patches/net/minecraft/network/NetHandlerPlayServer.java.patch +++ b/patches/net/minecraft/network/NetHandlerPlayServer.java.patch @@ -1140,18 +1140,27 @@ + if (this.playerEntity.dimension == 1) // coming from end + { + // We really should be calling transferPlayerToDimension since the player is coming in contact with a portal. -+ this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, true); // set flag to indicate player is leaving end. ++ this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL, null); // set flag to indicate player is leaving end. } + else + // not coming from end + { -+ this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, false); ++ this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, null); + } + // Cauldron end + } else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled()) { if (this.serverController.isSinglePlayer() && this.playerEntity.getCommandSenderName().equals(this.serverController.getServerOwner())) +@@ -857,7 +1612,7 @@ + return; + } + +- this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, playerEntity.dimension, false); ++ this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, playerEntity.dimension, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.DEATH, null); + } + + break; @@ -871,17 +1626,461 @@ public void processCloseWindow(C0DPacketCloseWindow p_147356_1_) diff --git a/patches/net/minecraft/server/management/ServerConfigurationManager.java.patch b/patches/net/minecraft/server/management/ServerConfigurationManager.java.patch index f8fca46..c3b33b2 100644 --- a/patches/net/minecraft/server/management/ServerConfigurationManager.java.patch +++ b/patches/net/minecraft/server/management/ServerConfigurationManager.java.patch @@ -381,7 +381,7 @@ public EntityPlayerMP createPlayerForUser(GameProfile p_148545_1_) { UUID uuid = EntityPlayer.func_146094_a(p_148545_1_); -@@ -410,80 +620,200 @@ +@@ -410,80 +620,199 @@ return new EntityPlayerMP(this.mcServer, this.mcServer.worldServerForDimension(0), p_148545_1_, (ItemInWorldManager)object); } @@ -451,10 +451,10 @@ + // Cauldron start - refactor entire method for sanity. + public EntityPlayerMP respawnPlayer(EntityPlayerMP par1EntityPlayerMP, int par2, boolean par3) + { -+ return this.respawnPlayer(par1EntityPlayerMP, par2, par3, null, TeleportCause.DEATH); ++ return this.respawnPlayer(par1EntityPlayerMP, par2, par3 ? TeleportCause.END_PORTAL : TeleportCause.UNKNOWN, null); + } + -+ public EntityPlayerMP respawnPlayer(EntityPlayerMP par1EntityPlayerMP, int targetDimension, boolean returnFromEnd, Location location, TeleportCause cause) ++ public EntityPlayerMP respawnPlayer(EntityPlayerMP par1EntityPlayerMP, int targetDimension, TeleportCause cause, Location location) + { + // Phase 1 - check if the player is allowed to respawn in same dimension + World world = mcServer.worldServerForDimension(targetDimension); @@ -470,7 +470,7 @@ + } + + // Phase 2 - handle return from End -+ if (returnFromEnd) ++ if (cause == TeleportCause.END_PORTAL) + { + WorldServer exitWorld = this.mcServer.worldServerForDimension(targetDimension); + Location enter = par1EntityPlayerMP.getBukkitEntity().getLocation(); @@ -488,7 +488,7 @@ + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null) + { -+ return par1EntityPlayerMP; ++ return null; + } + } + @@ -504,9 +504,8 @@ + boolean spawnForced = par1EntityPlayerMP.isSpawnForced(targetDimension); + par1EntityPlayerMP.dimension = targetDimension; + // CraftBukkit start -+ EntityPlayerMP entityplayermp1 = par1EntityPlayerMP; ++ EntityPlayerMP entityplayermp1 = kcauldron.ReverseClonner.clone(par1EntityPlayerMP, cause == TeleportCause.DEATH); + entityplayermp1.setWorld(this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension)); // make sure to update reference for bed spawn logic -+ MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerEvent.Clone(entityplayermp1, entityplayermp1, cause == TeleportCause.DEATH)); + entityplayermp1.playerConqueredTheEnd = false; ChunkCoordinates chunkcoordinates1; + boolean isBedSpawn = false; @@ -614,7 +613,7 @@ entityplayermp1.setHealth(entityplayermp1.getHealth()); - FMLCommonHandler.instance().firePlayerRespawnEvent(entityplayermp1); + // If world changed then fire the appropriate change world event else respawn -+ if (fromWorld != location.getWorld()) ++ if (fromWorld != location.getWorld() && cause != TeleportCause.DEATH) + FMLCommonHandler.instance().firePlayerChangedDimensionEvent(entityplayermp1, ((CraftWorld) fromWorld).getHandle().provider.dimensionId, + ((CraftWorld) location.getWorld()).getHandle().provider.dimensionId, (CraftWorld) fromWorld); // Cauldron - fire forge changed dimension event + else @@ -622,7 +621,7 @@ return entityplayermp1; } -@@ -492,34 +822,112 @@ +@@ -492,34 +821,112 @@ transferPlayerToDimension(p_72356_1_, p_72356_2_, mcServer.worldServerForDimension(p_72356_2_).getDefaultTeleporter()); } @@ -754,7 +753,7 @@ } public void transferEntityToWorld(Entity p_82448_1_, int p_82448_2_, WorldServer p_82448_3_, WorldServer p_82448_4_, Teleporter teleporter) -@@ -605,6 +1013,109 @@ +@@ -605,6 +1012,109 @@ p_82448_1_.setWorld(p_82448_4_); } @@ -864,7 +863,7 @@ public void sendPlayerInfoToAllPlayers() { if (++this.playerPingIndex > 600) -@@ -612,11 +1123,13 @@ +@@ -612,11 +1122,13 @@ this.playerPingIndex = 0; } @@ -878,7 +877,7 @@ } public void sendPacketToAllPlayers(Packet p_148540_1_) -@@ -877,13 +1390,24 @@ +@@ -877,13 +1389,24 @@ for (int j = 0; j < this.playerEntityList.size(); ++j) { EntityPlayerMP entityplayermp = (EntityPlayerMP)this.playerEntityList.get(j); @@ -905,7 +904,7 @@ if (d4 * d4 + d5 * d5 + d6 * d6 < p_148543_8_ * p_148543_8_) { entityplayermp.playerNetServerHandler.sendPacket(p_148543_11_); -@@ -941,13 +1465,16 @@ +@@ -941,13 +1464,16 @@ p_72354_1_.playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(1, 0.0F)); p_72354_1_.playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(7, p_72354_2_.getRainStrength(1.0F))); p_72354_1_.playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(8, p_72354_2_.getWeightedThunderStrength(1.0F))); @@ -923,7 +922,7 @@ p_72385_1_.playerNetServerHandler.sendPacket(new S09PacketHeldItemChange(p_72385_1_.inventory.currentItem)); } -@@ -961,9 +1488,17 @@ +@@ -961,9 +1487,17 @@ return this.maxPlayers; } @@ -942,7 +941,7 @@ } public void setWhiteListEnabled(boolean p_72371_1_) -@@ -1032,12 +1567,30 @@ +@@ -1032,12 +1566,30 @@ public void removeAllPlayers() { diff --git a/src/main/java/kcauldron/ReverseClonner.java b/src/main/java/kcauldron/ReverseClonner.java new file mode 100644 index 0000000..18c4b68 --- /dev/null +++ b/src/main/java/kcauldron/ReverseClonner.java @@ -0,0 +1,24 @@ +package kcauldron; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ContainerPlayer; +import net.minecraft.server.management.ItemInWorldManager; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.PlayerEvent; + +public enum ReverseClonner { + ; + public static EntityPlayerMP clone(EntityPlayerMP player, boolean wasDeath) { + EntityPlayerMP shadowCopy = new EntityPlayerMP(player.mcServer, (WorldServer) player.worldObj, + player.getGameProfile(), new ItemInWorldManager(player.worldObj)); + shadowCopy.clonePlayer(player, true); + if (wasDeath) { + player.inventory.clearInventory(null, -1); + player.inventoryContainer = new ContainerPlayer(player.inventory, !player.worldObj.isRemote, player); + } + MinecraftForge.EVENT_BUS.post(new PlayerEvent.Clone(player, shadowCopy, wasDeath)); + return player; + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java index c1ccc62..d128163 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -27,8 +27,6 @@ import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.plugin.Plugin; -import net.minecraft.entity.EntityLivingBase; - public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { private CraftInventoryPlayer inventory; private CraftInventory enderChest; @@ -40,13 +38,6 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { super(server, entity); mode = server.getDefaultGameMode(); } - - @Override - public void updateEntity(EntityLivingBase entity) { - super.updateEntity(entity); - if (inventory != null) inventory.updateInventory(((net.minecraft.entity.player.EntityPlayer) entity).inventory); - if (enderChest != null) enderChest.updateInventory(((net.minecraft.entity.player.EntityPlayer) entity).getInventoryEnderChest()); - } public String getName() { return getHandle().getCommandSenderName(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index cfa9d18..0945436 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -48,18 +48,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public Class entityClass; public String entityName; // Cauldron end - - public void updateEntity(net.minecraft.entity.EntityLivingBase entity) { - super.entity = entity; + + public CraftLivingEntity(final CraftServer server, final net.minecraft.entity.EntityLivingBase entity) { + super(server, entity); + // Cauldron start this.entityClass = entity.getClass(); this.entityName = EntityRegistry.getCustomEntityTypeName(entityClass); if (entityName == null) entityName = entity.getCommandSenderName(); - } - - public CraftLivingEntity(final CraftServer server, final net.minecraft.entity.EntityLivingBase entity) { - super(server, entity); - updateEntity(entity); // KCauldron + // Cauldron end if (entity instanceof net.minecraft.entity.EntityLiving) { equipment = new CraftEntityEquipment(this); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 01bf360..eeedd48 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -55,6 +55,7 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerRegisterChannelEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerUnregisterChannelEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.inventory.InventoryView.Property; import org.bukkit.map.MapView; import org.bukkit.metadata.MetadataValue; @@ -503,7 +504,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (fromWorld == toWorld) { entity.playerNetServerHandler.teleport(to); } else { - server.getHandle().respawnPlayer(entity, toWorld.dimension, false, to, cause); // Cauldron + server.getHandle().respawnPlayer(entity, toWorld.dimension, cause, to); // Cauldron } return true; } @@ -1324,7 +1325,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { { if ( getHealth() <= 0 && isOnline() ) { - server.getServer().getConfigurationManager().respawnPlayer( getHandle(), 0, false ); + server.getServer().getConfigurationManager().respawnPlayer( getHandle(), 0, TeleportCause.DEATH, null ); } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java index b97d258..21674ad 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -17,15 +17,11 @@ import org.bukkit.Material; public class CraftInventory implements Inventory { - protected net.minecraft.inventory.IInventory inventory; + protected final net.minecraft.inventory.IInventory inventory; public CraftInventory(net.minecraft.inventory.IInventory inventory) { this.inventory = inventory; } - - public void updateInventory(net.minecraft.inventory.IInventory inventory) { - this.inventory = inventory; - } public net.minecraft.inventory.IInventory getInventory() { return inventory; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java index d68b9e7..0a7d132 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java @@ -11,7 +11,7 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i public CraftInventoryPlayer(net.minecraft.entity.player.InventoryPlayer inventory) { super(inventory); } - + @Override public net.minecraft.entity.player.InventoryPlayer getInventory() { return (net.minecraft.entity.player.InventoryPlayer) inventory;