001 package net.minecraft.src; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 006 import net.minecraftforge.common.MinecraftForge; 007 import net.minecraftforge.event.world.ChunkWatchEvent; 008 009 public class PlayerInstance 010 { 011 public final List playersInChunk; 012 013 /** note: this is final */ 014 private final ChunkCoordIntPair chunkLocation; 015 private short[] locationOfBlockChange; 016 private int numberOfTilesToUpdate; 017 private int field_73260_f; 018 019 final PlayerManager myManager; 020 021 public PlayerInstance(PlayerManager par1PlayerManager, int par2, int par3) 022 { 023 this.myManager = par1PlayerManager; 024 this.playersInChunk = new ArrayList(); 025 this.locationOfBlockChange = new short[64]; 026 this.numberOfTilesToUpdate = 0; 027 this.chunkLocation = new ChunkCoordIntPair(par2, par3); 028 par1PlayerManager.getWorldServer().theChunkProviderServer.loadChunk(par2, par3); 029 } 030 031 /** 032 * called for all chunks within the visible radius of the player 033 */ 034 public void addPlayerToChunkWatchingList(EntityPlayerMP par1EntityPlayerMP) 035 { 036 if (this.playersInChunk.contains(par1EntityPlayerMP)) 037 { 038 throw new IllegalStateException("Failed to add player. " + par1EntityPlayerMP + " already is in chunk " + this.chunkLocation.chunkXPos + ", " + this.chunkLocation.chunkZPos); 039 } 040 else 041 { 042 this.playersInChunk.add(par1EntityPlayerMP); 043 par1EntityPlayerMP.loadedChunks.add(this.chunkLocation); 044 } 045 } 046 047 public void sendThisChunkToPlayer(EntityPlayerMP par1EntityPlayerMP) 048 { 049 if (this.playersInChunk.contains(par1EntityPlayerMP)) 050 { 051 par1EntityPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet51MapChunk(PlayerManager.getWorldServer(this.myManager).getChunkFromChunkCoords(this.chunkLocation.chunkXPos, this.chunkLocation.chunkZPos), true, 0)); 052 this.playersInChunk.remove(par1EntityPlayerMP); 053 par1EntityPlayerMP.loadedChunks.remove(this.chunkLocation); 054 055 MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.UnWatch(chunkLocation, par1EntityPlayerMP)); 056 057 if (this.playersInChunk.isEmpty()) 058 { 059 long var2 = (long)this.chunkLocation.chunkXPos + 2147483647L | (long)this.chunkLocation.chunkZPos + 2147483647L << 32; 060 PlayerManager.getChunkWatchers(this.myManager).remove(var2); 061 062 if (this.numberOfTilesToUpdate > 0) 063 { 064 PlayerManager.getChunkWatchersWithPlayers(this.myManager).remove(this); 065 } 066 067 this.myManager.getWorldServer().theChunkProviderServer.unloadChunksIfNotNearSpawn(this.chunkLocation.chunkXPos, this.chunkLocation.chunkZPos); 068 } 069 } 070 } 071 072 public void flagChunkForUpdate(int par1, int par2, int par3) 073 { 074 if (this.numberOfTilesToUpdate == 0) 075 { 076 PlayerManager.getChunkWatchersWithPlayers(this.myManager).add(this); 077 } 078 079 this.field_73260_f |= 1 << (par2 >> 4); 080 081 if (this.numberOfTilesToUpdate < 64) 082 { 083 short var4 = (short)(par1 << 12 | par3 << 8 | par2); 084 085 for (int var5 = 0; var5 < this.numberOfTilesToUpdate; ++var5) 086 { 087 if (this.locationOfBlockChange[var5] == var4) 088 { 089 return; 090 } 091 } 092 093 this.locationOfBlockChange[this.numberOfTilesToUpdate++] = var4; 094 } 095 } 096 097 public void sendToAllPlayersWatchingChunk(Packet par1Packet) 098 { 099 for (int var2 = 0; var2 < this.playersInChunk.size(); ++var2) 100 { 101 EntityPlayerMP var3 = (EntityPlayerMP)this.playersInChunk.get(var2); 102 103 if (!var3.loadedChunks.contains(this.chunkLocation)) 104 { 105 var3.playerNetServerHandler.sendPacketToPlayer(par1Packet); 106 } 107 } 108 } 109 110 public void sendChunkUpdate() 111 { 112 if (this.numberOfTilesToUpdate != 0) 113 { 114 int var1; 115 int var2; 116 int var3; 117 118 if (this.numberOfTilesToUpdate == 1) 119 { 120 var1 = this.chunkLocation.chunkXPos * 16 + (this.locationOfBlockChange[0] >> 12 & 15); 121 var2 = this.locationOfBlockChange[0] & 255; 122 var3 = this.chunkLocation.chunkZPos * 16 + (this.locationOfBlockChange[0] >> 8 & 15); 123 this.sendToAllPlayersWatchingChunk(new Packet53BlockChange(var1, var2, var3, PlayerManager.getWorldServer(this.myManager))); 124 125 if (PlayerManager.getWorldServer(this.myManager).blockHasTileEntity(var1, var2, var3)) 126 { 127 this.sendTileToAllPlayersWatchingChunk(PlayerManager.getWorldServer(this.myManager).getBlockTileEntity(var1, var2, var3)); 128 } 129 } 130 else 131 { 132 int var4; 133 134 if (this.numberOfTilesToUpdate == 64) 135 { 136 var1 = this.chunkLocation.chunkXPos * 16; 137 var2 = this.chunkLocation.chunkZPos * 16; 138 this.sendToAllPlayersWatchingChunk(new Packet51MapChunk(PlayerManager.getWorldServer(this.myManager).getChunkFromChunkCoords(this.chunkLocation.chunkXPos, this.chunkLocation.chunkZPos), false, this.field_73260_f)); 139 140 for (var3 = 0; var3 < 16; ++var3) 141 { 142 if ((this.field_73260_f & 1 << var3) != 0) 143 { 144 var4 = var3 << 4; 145 //BugFix: 16 makes it load an extra chunk, which isn't associated with a player, which makes it not unload unless a player walks near it. 146 //ToDo: Find a way to efficiently clean abandoned chunks. 147 //List var5 = PlayerManager.getWorldServer(this.myManager).getAllTileEntityInBox(var1, var4, var2, var1 + 16, var4 + 16, var2 + 16); 148 List var5 = PlayerManager.getWorldServer(this.myManager).getAllTileEntityInBox(var1, var4, var2, var1 + 15, var4 + 16, var2 + 15); 149 150 for (int var6 = 0; var6 < var5.size(); ++var6) 151 { 152 this.sendTileToAllPlayersWatchingChunk((TileEntity)var5.get(var6)); 153 } 154 } 155 } 156 } 157 else 158 { 159 this.sendToAllPlayersWatchingChunk(new Packet52MultiBlockChange(this.chunkLocation.chunkXPos, this.chunkLocation.chunkZPos, this.locationOfBlockChange, this.numberOfTilesToUpdate, PlayerManager.getWorldServer(this.myManager))); 160 161 for (var1 = 0; var1 < this.numberOfTilesToUpdate; ++var1) 162 { 163 var2 = this.chunkLocation.chunkXPos * 16 + (this.locationOfBlockChange[var1] >> 12 & 15); 164 var3 = this.locationOfBlockChange[var1] & 255; 165 var4 = this.chunkLocation.chunkZPos * 16 + (this.locationOfBlockChange[var1] >> 8 & 15); 166 167 if (PlayerManager.getWorldServer(this.myManager).blockHasTileEntity(var2, var3, var4)) 168 { 169 this.sendTileToAllPlayersWatchingChunk(PlayerManager.getWorldServer(this.myManager).getBlockTileEntity(var2, var3, var4)); 170 } 171 } 172 } 173 } 174 175 this.numberOfTilesToUpdate = 0; 176 this.field_73260_f = 0; 177 } 178 } 179 180 private void sendTileToAllPlayersWatchingChunk(TileEntity par1TileEntity) 181 { 182 if (par1TileEntity != null) 183 { 184 Packet var2 = par1TileEntity.getDescriptionPacket(); 185 186 if (var2 != null) 187 { 188 this.sendToAllPlayersWatchingChunk(var2); 189 } 190 } 191 } 192 193 static ChunkCoordIntPair getChunkLocation(PlayerInstance par0PlayerInstance) 194 { 195 return par0PlayerInstance.chunkLocation; 196 } 197 198 static List getPlayersInChunk(PlayerInstance par0PlayerInstance) 199 { 200 return par0PlayerInstance.playersInChunk; 201 } 202 }