From 5f203ce8089bf8284dc6d736c0b1b64fb6327063 Mon Sep 17 00:00:00 2001 From: XCompWiz Date: Sat, 6 Jul 2013 15:39:28 +0300 Subject: [PATCH] Makes player-specific spawnpoints dimension aware Makes ServerConfigurationManager correctly get player-specific spawn point for the target dimension Changes EntityPlayer to store and save a (bed) spawn point for every dimension, as well as transfer them to respawn "clones" --- .../entity/player/EntityPlayer.java.patch | 210 +++++++++++++++--- .../ServerConfigurationManager.java.patch | 11 +- 2 files changed, 193 insertions(+), 28 deletions(-) diff --git a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch index 582b79133..7e9ccb2ac 100644 --- a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch +++ b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch @@ -1,6 +1,18 @@ --- ../src_base/minecraft/net/minecraft/entity/player/EntityPlayer.java +++ ../src_work/minecraft/net/minecraft/entity/player/EntityPlayer.java -@@ -68,8 +68,21 @@ +@@ -5,8 +5,11 @@ + import cpw.mods.fml.relauncher.Side; + import cpw.mods.fml.relauncher.SideOnly; + import java.util.Collection; ++import java.util.HashMap; + import java.util.Iterator; + import java.util.List; ++import java.util.Map.Entry; ++ + import net.minecraft.block.Block; + import net.minecraft.block.BlockBed; + import net.minecraft.block.material.Material; +@@ -68,8 +71,21 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; @@ -22,7 +34,21 @@ /** Inventory of the player */ public InventoryPlayer inventory = new InventoryPlayer(this); private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest(); -@@ -269,6 +282,7 @@ +@@ -122,11 +138,13 @@ + * Holds the last coordinate to spawn based on last bed that the player sleep. + */ + private ChunkCoordinates spawnChunk; ++ private HashMap spawnChunkMap = new HashMap(); + + /** + * Whether this player's spawn point is forced, preventing execution of bed checks. + */ + private boolean spawnForced; ++ private HashMap spawnForcedMap = new HashMap(); + + /** Holds the coordinate of the player when enter a minecraft to ride. */ + private ChunkCoordinates startMinecartRidingCoordinate; +@@ -269,6 +287,7 @@ if (itemstack == this.itemInUse) { @@ -30,7 +56,7 @@ if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0) { this.updateItemUse(itemstack, 5); -@@ -539,11 +553,11 @@ +@@ -539,11 +558,11 @@ this.cameraYaw = 0.0F; this.addMountedMovementStat(this.posX - d0, this.posY - d1, this.posZ - d2); @@ -44,7 +70,7 @@ } } } -@@ -686,11 +700,15 @@ +@@ -686,11 +705,15 @@ */ public void onDeath(DamageSource par1DamageSource) { @@ -60,7 +86,7 @@ if (this.username.equals("Notch")) { this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true); -@@ -699,6 +717,20 @@ +@@ -699,6 +722,20 @@ if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory")) { this.inventory.dropAllItems(); @@ -81,7 +107,7 @@ } if (par1DamageSource != null) -@@ -749,7 +781,20 @@ +@@ -749,7 +786,20 @@ */ public EntityItem dropOneItem(boolean par1) { @@ -103,7 +129,7 @@ } /** -@@ -758,7 +803,7 @@ +@@ -758,7 +808,7 @@ */ public EntityItem dropPlayerItem(ItemStack par1ItemStack) { @@ -112,7 +138,7 @@ } /** -@@ -814,15 +859,28 @@ +@@ -814,15 +864,28 @@ */ public void joinEntityItemWithWorld(EntityItem par1EntityItem) { @@ -143,7 +169,7 @@ if (f > 1.0F) { -@@ -833,7 +891,9 @@ +@@ -833,7 +896,9 @@ { float f1 = (float)(i * i + 1); @@ -154,7 +180,7 @@ { f += f1 * 0.08F; } -@@ -864,7 +924,8 @@ +@@ -864,7 +929,8 @@ f /= 5.0F; } @@ -164,7 +190,7 @@ } /** -@@ -872,7 +933,7 @@ +@@ -872,7 +938,7 @@ */ public boolean canHarvestBlock(Block par1Block) { @@ -173,7 +199,44 @@ } /** -@@ -982,6 +1043,7 @@ +@@ -902,6 +968,14 @@ + this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"), par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ")); + this.spawnForced = par1NBTTagCompound.getBoolean("SpawnForced"); + } ++ NBTTagList spawnlist = null; ++ spawnlist = par1NBTTagCompound.getTagList("Spawns"); ++ for (int i = 0; i < spawnlist.tagCount(); ++i) { ++ NBTTagCompound spawndata = (NBTTagCompound)spawnlist.tagAt(i); ++ int spawndim = spawndata.getInteger("Dim"); ++ this.spawnChunkMap.put(spawndim, new ChunkCoordinates(spawndata.getInteger("SpawnX"), spawndata.getInteger("SpawnY"), spawndata.getInteger("SpawnZ"))); ++ this.spawnForcedMap.put(spawndim, spawndata.getBoolean("SpawnForced")); ++ } + + this.foodStats.readNBT(par1NBTTagCompound); + this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound); +@@ -935,6 +1009,21 @@ + par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ); + par1NBTTagCompound.setBoolean("SpawnForced", this.spawnForced); + } ++ NBTTagList spawnlist = new NBTTagList(); ++ for (Entry entry : this.spawnChunkMap.entrySet()) { ++ NBTTagCompound spawndata = new NBTTagCompound(); ++ ChunkCoordinates spawn = entry.getValue(); ++ if (spawn == null) continue; ++ Boolean forced = spawnForcedMap.get(entry.getKey()); ++ if (forced == null) forced = false; ++ spawndata.setInteger("Dim", entry.getKey()); ++ spawndata.setInteger("SpawnX", spawn.posX); ++ spawndata.setInteger("SpawnY", spawn.posY); ++ spawndata.setInteger("SpawnZ", spawn.posZ); ++ spawndata.setBoolean("SpawnForced", forced); ++ spawnlist.appendTag(spawndata); ++ } ++ par1NBTTagCompound.setTag("Spawns", spawnlist); + + this.foodStats.writeNBT(par1NBTTagCompound); + this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound); +@@ -982,6 +1071,7 @@ */ public boolean attackEntityFrom(DamageSource par1DamageSource, float par2) { @@ -181,7 +244,7 @@ if (this.isEntityInvulnerable()) { return false; -@@ -1135,12 +1197,15 @@ +@@ -1135,12 +1225,15 @@ { if (!this.isEntityInvulnerable()) { @@ -198,7 +261,7 @@ par2 = this.applyPotionDamageCalculations(par1DamageSource, par2); float f1 = par2; par2 = Math.max(par2 - this.func_110139_bj(), 0.0F); -@@ -1190,6 +1255,7 @@ +@@ -1190,6 +1283,7 @@ public boolean interactWith(Entity par1Entity) { @@ -206,7 +269,7 @@ ItemStack itemstack = this.getCurrentEquippedItem(); ItemStack itemstack1 = itemstack != null ? itemstack.copy() : null; -@@ -1246,7 +1312,9 @@ +@@ -1246,7 +1340,9 @@ */ public void destroyCurrentEquippedItem() { @@ -216,7 +279,7 @@ } /** -@@ -1263,6 +1331,15 @@ +@@ -1263,6 +1359,15 @@ */ public void attackTargetEntityWithCurrentItem(Entity par1Entity) { @@ -232,7 +295,7 @@ if (par1Entity.canAttackWithItem()) { if (!par1Entity.func_85031_j(this)) -@@ -1421,6 +1498,12 @@ +@@ -1421,6 +1526,12 @@ */ public EnumStatus sleepInBedAt(int par1, int par2, int par3) { @@ -245,7 +308,7 @@ if (!this.worldObj.isRemote) { if (this.isPlayerSleeping() || !this.isEntityAlive()) -@@ -1465,6 +1548,11 @@ +@@ -1465,6 +1576,11 @@ { int l = this.worldObj.getBlockMetadata(par1, par2, par3); int i1 = BlockBed.getDirection(l); @@ -257,7 +320,7 @@ float f = 0.5F; float f1 = 0.5F; -@@ -1535,10 +1623,12 @@ +@@ -1535,10 +1651,12 @@ ChunkCoordinates chunkcoordinates = this.playerLocation; ChunkCoordinates chunkcoordinates1 = this.playerLocation; @@ -274,7 +337,7 @@ if (chunkcoordinates1 == null) { -@@ -1575,7 +1665,9 @@ +@@ -1575,7 +1693,9 @@ */ private boolean isInBed() { @@ -285,7 +348,7 @@ } /** -@@ -1590,9 +1682,12 @@ +@@ -1590,9 +1710,12 @@ ichunkprovider.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4); ichunkprovider.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4); @@ -301,7 +364,7 @@ return chunkcoordinates1; } else -@@ -1614,10 +1709,13 @@ +@@ -1614,10 +1737,13 @@ { if (this.playerLocation != null) { @@ -319,7 +382,97 @@ { case 0: return 90.0F; -@@ -1891,6 +1989,10 @@ +@@ -1683,14 +1809,40 @@ + /** + * Returns the location of the bed the player will respawn at, or null if the player has not slept in a bed. + */ ++ @Deprecated + public ChunkCoordinates getBedLocation() + { +- return this.spawnChunk; +- } +- ++ return getBedLocation(this.dimension); ++ } ++ ++ @Deprecated + public boolean isSpawnForced() + { +- return this.spawnForced; ++ return isSpawnForced(this.dimension); ++ } ++ ++ /** ++ * A dimension aware version of getBedLocation. ++ * @param dimension The dimension to get the bed spawn for ++ * @return The player specific spawn location for the dimension. May be null. ++ */ ++ public ChunkCoordinates getBedLocation(int dimension) { ++ if (dimension == 0) return this.spawnChunk; ++ return this.spawnChunkMap.get(dimension); ++ } ++ ++ /** ++ * A dimension aware version of isSpawnForced. ++ * Noramally isSpawnForced is used to determine if the respawn system should check for a bed or not. ++ * This just extends that to be dimension aware. ++ * @param dimension The dimension to get whether to check for a bed before spawning for ++ * @return The player specific spawn location for the dimension. May be null. ++ */ ++ public boolean isSpawnForced(int dimension) { ++ if (dimension == 0) return this.spawnForced; ++ Boolean forced = this.spawnForcedMap.get(dimension); ++ if (forced == null) return false; ++ return forced; + } + + /** +@@ -1698,6 +1850,10 @@ + */ + public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2) + { ++ if (this.dimension != 0) { ++ setSpawnChunk(par1ChunkCoordinates, par2, this.dimension); ++ return; ++ } + if (par1ChunkCoordinates != null) + { + this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates); +@@ -1709,7 +1865,32 @@ + this.spawnForced = false; + } + } +- ++ /** ++ * A dimension aware version of setSpawnChunk. ++ * This functions identically, but allows you to specify which dimension to affect, rather than affecting the player's current dimension. ++ * @param chunkCoordinates The spawn point to set as the player-specific spawn point for the dimension ++ * @param forced Whether or not the respawn code should check for a bed at this location (true means it won't check for a bed) ++ * @param dimension Which dimension to apply the player-specific respawn point to ++ */ ++ public void setSpawnChunk(ChunkCoordinates chunkCoordinates, boolean forced, int dimension) { ++ if (dimension == 0) { ++ if (chunkCoordinates != null) { ++ this.spawnChunk = new ChunkCoordinates(chunkCoordinates); ++ this.spawnForced = forced; ++ } else { ++ this.spawnChunk = null; ++ this.spawnForced = false; ++ } ++ return; ++ } ++ if (chunkCoordinates != null) { ++ this.spawnChunkMap.put(dimension, new ChunkCoordinates(chunkCoordinates)); ++ this.spawnForcedMap.put(dimension, forced); ++ } else { ++ this.spawnChunkMap.remove(dimension); ++ this.spawnForcedMap.remove(dimension); ++ } ++ } + /** + * Will trigger the specified trigger. + */ +@@ -1891,6 +2072,10 @@ super.fall(par1); } @@ -330,7 +483,7 @@ } /** -@@ -1932,7 +2034,7 @@ +@@ -1932,7 +2117,7 @@ { if (par1ItemStack.getItem().requiresMultipleRenderPasses()) { @@ -339,7 +492,7 @@ } if (this.itemInUse != null && par1ItemStack.itemID == Item.bow.itemID) -@@ -1954,6 +2056,7 @@ +@@ -1954,6 +2139,7 @@ return Item.bow.getItemIconForUseDuration(0); } } @@ -347,9 +500,12 @@ } return icon; -@@ -2176,6 +2279,14 @@ +@@ -2175,7 +2361,17 @@ + this.setScore(par1EntityPlayer.getScore()); } ++ this.spawnChunkMap = par1EntityPlayer.spawnChunkMap; ++ this.spawnForcedMap = par1EntityPlayer.spawnForcedMap; this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest; + + //Copy over a section of the Entity Data from the old player. @@ -362,7 +518,7 @@ } /** -@@ -2239,7 +2350,14 @@ +@@ -2239,7 +2435,14 @@ */ public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) { diff --git a/patches/minecraft/net/minecraft/server/management/ServerConfigurationManager.java.patch b/patches/minecraft/net/minecraft/server/management/ServerConfigurationManager.java.patch index 2fe38a1dc..331f53fd2 100644 --- a/patches/minecraft/net/minecraft/server/management/ServerConfigurationManager.java.patch +++ b/patches/minecraft/net/minecraft/server/management/ServerConfigurationManager.java.patch @@ -15,7 +15,7 @@ public abstract class ServerConfigurationManager { -@@ -387,6 +391,16 @@ +@@ -387,13 +391,23 @@ */ public EntityPlayerMP respawnPlayer(EntityPlayerMP par1EntityPlayerMP, int par2, boolean par3) { @@ -32,6 +32,15 @@ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removePlayerFromTrackers(par1EntityPlayerMP); par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removeEntityFromAllTrackingPlayers(par1EntityPlayerMP); par1EntityPlayerMP.getServerForPlayer().getPlayerManager().removePlayer(par1EntityPlayerMP); + this.playerEntityList.remove(par1EntityPlayerMP); + this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension).removePlayerEntityDangerously(par1EntityPlayerMP); +- ChunkCoordinates chunkcoordinates = par1EntityPlayerMP.getBedLocation(); +- boolean flag1 = par1EntityPlayerMP.isSpawnForced(); ++ ChunkCoordinates chunkcoordinates = par1EntityPlayerMP.getBedLocation(par2); ++ boolean flag1 = par1EntityPlayerMP.isSpawnForced(par2); + par1EntityPlayerMP.dimension = par2; + Object object; + @@ -409,6 +423,7 @@ EntityPlayerMP entityplayermp1 = new EntityPlayerMP(this.mcServer, this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension), par1EntityPlayerMP.getCommandSenderName(), (ItemInWorldManager)object); entityplayermp1.playerNetServerHandler = par1EntityPlayerMP.playerNetServerHandler;