001 package net.minecraft.src; 002 003 import net.minecraftforge.common.ForgeHooks; 004 import net.minecraftforge.common.MinecraftForge; 005 import net.minecraftforge.event.Event; 006 import net.minecraftforge.event.ForgeEventFactory; 007 import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; 008 import net.minecraftforge.event.entity.player.PlayerInteractEvent; 009 import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; 010 011 public class ItemInWorldManager 012 { 013 /** Forge reach distance */ 014 private double blockReachDistance = 5.0d; 015 /** The world object that this object is connected to. */ 016 public World theWorld; 017 018 /** The EntityPlayerMP object that this object is connected to. */ 019 public EntityPlayerMP thisPlayerMP; 020 private EnumGameType gameType; 021 022 /** 023 * set to true on first call of destroyBlockInWorldPartially, false before any further calls 024 */ 025 private boolean isPartiallyDestroyedBlockWhole; 026 private int initialDamage; 027 private int partiallyDestroyedBlockX; 028 private int partiallyDestroyedBlockY; 029 private int partiallyDestroyedBlockZ; 030 private int curblockDamage; 031 private boolean field_73097_j; 032 private int posX; 033 private int posY; 034 private int posZ; 035 private int field_73093_n; 036 private int durabilityRemainingOnBlock; 037 038 public ItemInWorldManager(World par1World) 039 { 040 this.gameType = EnumGameType.NOT_SET; 041 this.durabilityRemainingOnBlock = -1; 042 this.theWorld = par1World; 043 } 044 045 public void setGameType(EnumGameType par1EnumGameType) 046 { 047 this.gameType = par1EnumGameType; 048 par1EnumGameType.configurePlayerCapabilities(this.thisPlayerMP.capabilities); 049 this.thisPlayerMP.sendPlayerAbilities(); 050 } 051 052 public EnumGameType getGameType() 053 { 054 return this.gameType; 055 } 056 057 /** 058 * Get if we are in creative game mode. 059 */ 060 public boolean isCreative() 061 { 062 return this.gameType.isCreative(); 063 } 064 065 /** 066 * if the gameType is currently NOT_SET then change it to par1 067 */ 068 public void initializeGameType(EnumGameType par1EnumGameType) 069 { 070 if (this.gameType == EnumGameType.NOT_SET) 071 { 072 this.gameType = par1EnumGameType; 073 } 074 075 this.setGameType(this.gameType); 076 } 077 078 public void updateBlockRemoving() 079 { 080 ++this.curblockDamage; 081 int var1; 082 float var4; 083 int var5; 084 085 if (this.field_73097_j) 086 { 087 var1 = this.curblockDamage - this.field_73093_n; 088 int var2 = this.theWorld.getBlockId(this.posX, this.posY, this.posZ); 089 090 if (var2 == 0) 091 { 092 this.field_73097_j = false; 093 } 094 else 095 { 096 Block var3 = Block.blocksList[var2]; 097 var4 = var3.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.posX, this.posY, this.posZ) * (float)(var1 + 1); 098 var5 = (int)(var4 * 10.0F); 099 100 if (var5 != this.durabilityRemainingOnBlock) 101 { 102 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.posX, this.posY, this.posZ, var5); 103 this.durabilityRemainingOnBlock = var5; 104 } 105 106 if (var4 >= 1.0F) 107 { 108 this.field_73097_j = false; 109 this.tryHarvestBlock(this.posX, this.posY, this.posZ); 110 } 111 } 112 } 113 else if (this.isPartiallyDestroyedBlockWhole) 114 { 115 var1 = this.theWorld.getBlockId(this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ); 116 Block var6 = Block.blocksList[var1]; 117 118 if (var6 == null) 119 { 120 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1); 121 this.durabilityRemainingOnBlock = -1; 122 this.isPartiallyDestroyedBlockWhole = false; 123 } 124 else 125 { 126 int var7 = this.curblockDamage - this.initialDamage; 127 var4 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ) * (float)(var7 + 1); 128 var5 = (int)(var4 * 10.0F); 129 130 if (var5 != this.durabilityRemainingOnBlock) 131 { 132 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, var5); 133 this.durabilityRemainingOnBlock = var5; 134 } 135 } 136 } 137 } 138 139 /** 140 * if not creative, it calls destroyBlockInWorldPartially untill the block is broken first. par4 is the specific 141 * side. tryHarvestBlock can also be the result of this call 142 */ 143 public void onBlockClicked(int par1, int par2, int par3, int par4) 144 { 145 if (!this.gameType.isAdventure() || this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) 146 { 147 PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(thisPlayerMP, Action.LEFT_CLICK_BLOCK, par1, par2, par3, par4); 148 if (event.isCanceled()) 149 { 150 thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); 151 return; 152 } 153 154 if (this.isCreative()) 155 { 156 if (!this.theWorld.extinguishFire((EntityPlayer)null, par1, par2, par3, par4)) 157 { 158 this.tryHarvestBlock(par1, par2, par3); 159 } 160 } 161 else 162 { 163 this.initialDamage = this.curblockDamage; 164 float var5 = 1.0F; 165 int var6 = this.theWorld.getBlockId(par1, par2, par3); 166 Block block = Block.blocksList[var6]; 167 168 if (block != null) 169 { 170 if (event.useBlock != Event.Result.DENY) 171 { 172 block.onBlockClicked(theWorld, par1, par2, par3, thisPlayerMP); 173 theWorld.extinguishFire(thisPlayerMP, par1, par2, par3, par4); 174 } 175 else 176 { 177 thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); 178 } 179 var5 = block.getPlayerRelativeBlockHardness(thisPlayerMP, thisPlayerMP.worldObj, par1, par2, par3); 180 } 181 182 if (event.useItem == Event.Result.DENY) 183 { 184 if (var5 >= 1.0f) 185 { 186 thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, theWorld)); 187 } 188 return; 189 } 190 191 if (var6 > 0 && var5 >= 1.0F) 192 { 193 this.tryHarvestBlock(par1, par2, par3); 194 } 195 else 196 { 197 this.isPartiallyDestroyedBlockWhole = true; 198 this.partiallyDestroyedBlockX = par1; 199 this.partiallyDestroyedBlockY = par2; 200 this.partiallyDestroyedBlockZ = par3; 201 int var7 = (int)(var5 * 10.0F); 202 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, var7); 203 this.durabilityRemainingOnBlock = var7; 204 } 205 } 206 } 207 } 208 209 public void uncheckedTryHarvestBlock(int par1, int par2, int par3) 210 { 211 if (par1 == this.partiallyDestroyedBlockX && par2 == this.partiallyDestroyedBlockY && par3 == this.partiallyDestroyedBlockZ) 212 { 213 int var4 = this.curblockDamage - this.initialDamage; 214 int var5 = this.theWorld.getBlockId(par1, par2, par3); 215 216 if (var5 != 0) 217 { 218 Block var6 = Block.blocksList[var5]; 219 float var7 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, par1, par2, par3) * (float)(var4 + 1); 220 221 if (var7 >= 0.7F) 222 { 223 this.isPartiallyDestroyedBlockWhole = false; 224 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, -1); 225 this.tryHarvestBlock(par1, par2, par3); 226 } 227 else if (!this.field_73097_j) 228 { 229 this.isPartiallyDestroyedBlockWhole = false; 230 this.field_73097_j = true; 231 this.posX = par1; 232 this.posY = par2; 233 this.posZ = par3; 234 this.field_73093_n = this.initialDamage; 235 } 236 } 237 } 238 } 239 240 /** 241 * note: this ignores the pars passed in and continues to destroy the onClickedBlock 242 */ 243 public void destroyBlockInWorldPartially(int par1, int par2, int par3) 244 { 245 this.isPartiallyDestroyedBlockWhole = false; 246 this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.partiallyDestroyedBlockX, this.partiallyDestroyedBlockY, this.partiallyDestroyedBlockZ, -1); 247 } 248 249 /** 250 * Removes a block and triggers the appropriate events 251 */ 252 private boolean removeBlock(int par1, int par2, int par3) 253 { 254 Block var4 = Block.blocksList[this.theWorld.getBlockId(par1, par2, par3)]; 255 int var5 = this.theWorld.getBlockMetadata(par1, par2, par3); 256 257 if (var4 != null) 258 { 259 var4.onBlockHarvested(this.theWorld, par1, par2, par3, var5, this.thisPlayerMP); 260 } 261 262 boolean var6 = (var4 != null && var4.removeBlockByPlayer(theWorld, thisPlayerMP, par1, par2, par3)); 263 264 if (var4 != null && var6) 265 { 266 var4.onBlockDestroyedByPlayer(this.theWorld, par1, par2, par3, var5); 267 } 268 269 return var6; 270 } 271 272 /** 273 * Attempts to harvest a block at the given coordinate 274 */ 275 public boolean tryHarvestBlock(int par1, int par2, int par3) 276 { 277 if (this.gameType.isAdventure() && !this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) 278 { 279 return false; 280 } 281 else 282 { 283 ItemStack stack = thisPlayerMP.getCurrentEquippedItem(); 284 if (stack != null && stack.getItem().onBlockStartBreak(stack, par1, par2, par3, thisPlayerMP)) 285 { 286 return false; 287 } 288 int var4 = this.theWorld.getBlockId(par1, par2, par3); 289 int var5 = this.theWorld.getBlockMetadata(par1, par2, par3); 290 this.theWorld.playAuxSFXAtEntity(this.thisPlayerMP, 2001, par1, par2, par3, var4 + (this.theWorld.getBlockMetadata(par1, par2, par3) << 12)); 291 boolean var6 = false; 292 293 if (this.isCreative()) 294 { 295 var6 = this.removeBlock(par1, par2, par3); 296 this.thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par1, par2, par3, this.theWorld)); 297 } 298 else 299 { 300 ItemStack var7 = this.thisPlayerMP.getCurrentEquippedItem(); 301 boolean var8 = false; 302 Block block = Block.blocksList[var4]; 303 if (block != null) 304 { 305 var8 = block.canHarvestBlock(thisPlayerMP, var5); 306 } 307 308 if (var7 != null) 309 { 310 var7.onBlockDestroyed(this.theWorld, var4, par1, par2, par3, this.thisPlayerMP); 311 312 if (var7.stackSize == 0) 313 { 314 this.thisPlayerMP.destroyCurrentEquippedItem(); 315 MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, var7)); 316 } 317 } 318 319 var6 = this.removeBlock(par1, par2, par3); 320 if (var6 && var8) 321 { 322 Block.blocksList[var4].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, var5); 323 } 324 } 325 326 return var6; 327 } 328 } 329 330 /** 331 * Attempts to right-click use an item by the given EntityPlayer in the given World 332 */ 333 public boolean tryUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack) 334 { 335 int var4 = par3ItemStack.stackSize; 336 int var5 = par3ItemStack.getItemDamage(); 337 ItemStack var6 = par3ItemStack.useItemRightClick(par2World, par1EntityPlayer); 338 339 if (var6 == par3ItemStack && (var6 == null || var6.stackSize == var4 && var6.getMaxItemUseDuration() <= 0 && var6.getItemDamage() == var5)) 340 { 341 return false; 342 } 343 else 344 { 345 par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = var6; 346 347 if (this.isCreative()) 348 { 349 var6.stackSize = var4; 350 351 if (var6.isItemStackDamageable()) 352 { 353 var6.setItemDamage(var5); 354 } 355 } 356 357 if (var6.stackSize == 0) 358 { 359 par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null; 360 MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thisPlayerMP, var6)); 361 } 362 363 if (!par1EntityPlayer.isUsingItem()) 364 { 365 ((EntityPlayerMP)par1EntityPlayer).sendContainerToPlayer(par1EntityPlayer.inventorySlots); 366 } 367 368 return true; 369 } 370 } 371 372 /** 373 * Activate the clicked on block, otherwise use the held item. Args: player, world, itemStack, x, y, z, side, 374 * xOffset, yOffset, zOffset 375 */ 376 public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack, int par4, int par5, int par6, int par7, float par8, float par9, float par10) 377 { 378 PlayerInteractEvent event = ForgeEventFactory.onPlayerInteract(par1EntityPlayer, Action.RIGHT_CLICK_BLOCK, par4, par5, par6, par7); 379 if (event.isCanceled()) 380 { 381 thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld)); 382 return false; 383 } 384 385 Item item = (par3ItemStack != null ? par3ItemStack.getItem() : null); 386 if (item != null && item.onItemUseFirst(par3ItemStack, par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10)) 387 { 388 if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack); 389 return true; 390 } 391 392 int var11 = par2World.getBlockId(par4, par5, par6); 393 Block block = Block.blocksList[var11]; 394 boolean result = false; 395 396 if (block != null) 397 { 398 if (event.useBlock != Event.Result.DENY) 399 { 400 result = block.onBlockActivated(par2World, par4, par5, par6, par1EntityPlayer, par7, par8, par9, par10); 401 } 402 else 403 { 404 thisPlayerMP.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(par4, par5, par6, theWorld)); 405 result = event.useItem != Event.Result.ALLOW; 406 } 407 } 408 409 if (par3ItemStack != null && !result) 410 { 411 int meta = par3ItemStack.getItemDamage(); 412 int size = par3ItemStack.stackSize; 413 result = par3ItemStack.tryPlaceItemIntoWorld(par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9, par10); 414 if (isCreative()) 415 { 416 par3ItemStack.setItemDamage(meta); 417 par3ItemStack.stackSize = size; 418 } 419 if (par3ItemStack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(thisPlayerMP, par3ItemStack); 420 } 421 422 /* Re-enable if this causes bukkit incompatibility, or re-write client side to only send a single packet per right click. 423 if (par3ItemStack != null && ((!result && event.useItem != Event.Result.DENY) || event.useItem == Event.Result.ALLOW)) 424 { 425 this.tryUseItem(thisPlayerMP, par2World, par3ItemStack); 426 }*/ 427 return result; 428 } 429 430 /** 431 * Sets the world instance. 432 */ 433 public void setWorld(WorldServer par1WorldServer) 434 { 435 this.theWorld = par1WorldServer; 436 } 437 438 public double getBlockReachDistance() 439 { 440 return blockReachDistance; 441 } 442 public void setBlockReachDistance(double distance) 443 { 444 blockReachDistance = distance; 445 } 446 }