001 package net.minecraft.tileentity; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import java.util.Iterator; 006 import java.util.List; 007 import net.minecraft.block.Block; 008 import net.minecraft.entity.player.EntityPlayer; 009 import net.minecraft.inventory.IInventory; 010 import net.minecraft.item.ItemStack; 011 import net.minecraft.nbt.NBTTagCompound; 012 import net.minecraft.network.packet.Packet; 013 import net.minecraft.network.packet.Packet132TileEntityData; 014 import net.minecraft.potion.Potion; 015 import net.minecraft.potion.PotionEffect; 016 import net.minecraft.util.AxisAlignedBB; 017 018 public class TileEntityBeacon extends TileEntity implements IInventory 019 { 020 /** List of effects that Beacon can apply */ 021 public static final Potion[][] effectsList = new Potion[][] {{Potion.moveSpeed, Potion.digSpeed}, {Potion.resistance, Potion.jump}, {Potion.damageBoost}, {Potion.regeneration}}; 022 @SideOnly(Side.CLIENT) 023 private long field_82137_b; 024 @SideOnly(Side.CLIENT) 025 private float field_82138_c; 026 private boolean field_82135_d; 027 028 /** Level of this beacon's pyramid. */ 029 private int levels = -1; 030 031 /** Primary potion effect given by this beacon. */ 032 private int primaryEffect; 033 034 /** Secondary potion effect given by this beacon. */ 035 private int secondaryEffect; 036 037 /** Item given to this beacon as payment. */ 038 private ItemStack payment; 039 040 /** 041 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count 042 * ticks and creates a new spawn inside its implementation. 043 */ 044 public void updateEntity() 045 { 046 if (this.worldObj.getTotalWorldTime() % 80L == 0L) 047 { 048 this.func_82131_u(); 049 this.func_82124_t(); 050 } 051 } 052 053 private void func_82124_t() 054 { 055 if (this.field_82135_d && this.levels > 0 && !this.worldObj.isRemote && this.primaryEffect > 0) 056 { 057 double var1 = (double)(this.levels * 8 + 8); 058 byte var3 = 0; 059 060 if (this.levels >= 4 && this.primaryEffect == this.secondaryEffect) 061 { 062 var3 = 1; 063 } 064 065 AxisAlignedBB var4 = AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, (double)(this.xCoord + 1), (double)(this.yCoord + 1), (double)(this.zCoord + 1)).expand(var1, var1, var1); 066 List var5 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, var4); 067 Iterator var6 = var5.iterator(); 068 EntityPlayer var7; 069 070 while (var6.hasNext()) 071 { 072 var7 = (EntityPlayer)var6.next(); 073 var7.addPotionEffect(new PotionEffect(this.primaryEffect, 180, var3, true)); 074 } 075 076 if (this.levels >= 4 && this.primaryEffect != this.secondaryEffect && this.secondaryEffect > 0) 077 { 078 var6 = var5.iterator(); 079 080 while (var6.hasNext()) 081 { 082 var7 = (EntityPlayer)var6.next(); 083 var7.addPotionEffect(new PotionEffect(this.secondaryEffect, 180, 0, true)); 084 } 085 } 086 } 087 } 088 089 private void func_82131_u() 090 { 091 if (!this.worldObj.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) 092 { 093 this.field_82135_d = false; 094 this.levels = 0; 095 } 096 else 097 { 098 this.field_82135_d = true; 099 this.levels = 0; 100 101 for (int var1 = 1; var1 <= 4; this.levels = var1++) 102 { 103 int var2 = this.yCoord - var1; 104 105 if (var2 < 0) 106 { 107 break; 108 } 109 110 boolean var3 = true; 111 112 for (int var4 = this.xCoord - var1; var4 <= this.xCoord + var1 && var3; ++var4) 113 { 114 for (int var5 = this.zCoord - var1; var5 <= this.zCoord + var1; ++var5) 115 { 116 int var6 = this.worldObj.getBlockId(var4, var2, var5); 117 Block block = Block.blocksList[var6]; 118 119 if (block == null || !block.isBeaconBase(worldObj, var4, var2, var5, xCoord, yCoord, zCoord)) 120 { 121 var3 = false; 122 break; 123 } 124 } 125 } 126 127 if (!var3) 128 { 129 break; 130 } 131 } 132 133 if (this.levels == 0) 134 { 135 this.field_82135_d = false; 136 } 137 } 138 } 139 140 @SideOnly(Side.CLIENT) 141 public float func_82125_v_() 142 { 143 if (!this.field_82135_d) 144 { 145 return 0.0F; 146 } 147 else 148 { 149 int var1 = (int)(this.worldObj.getTotalWorldTime() - this.field_82137_b); 150 this.field_82137_b = this.worldObj.getTotalWorldTime(); 151 152 if (var1 > 1) 153 { 154 this.field_82138_c -= (float)var1 / 40.0F; 155 156 if (this.field_82138_c < 0.0F) 157 { 158 this.field_82138_c = 0.0F; 159 } 160 } 161 162 this.field_82138_c += 0.025F; 163 164 if (this.field_82138_c > 1.0F) 165 { 166 this.field_82138_c = 1.0F; 167 } 168 169 return this.field_82138_c; 170 } 171 } 172 173 /** 174 * Return the primary potion effect given by this beacon. 175 */ 176 public int getPrimaryEffect() 177 { 178 return this.primaryEffect; 179 } 180 181 /** 182 * Return the secondary potion effect given by this beacon. 183 */ 184 public int getSecondaryEffect() 185 { 186 return this.secondaryEffect; 187 } 188 189 /** 190 * Return the levels of this beacon's pyramid. 191 */ 192 public int getLevels() 193 { 194 return this.levels; 195 } 196 197 @SideOnly(Side.CLIENT) 198 199 /** 200 * Set the levels of this beacon's pyramid. 201 */ 202 public void setLevels(int par1) 203 { 204 this.levels = par1; 205 } 206 207 public void func_82128_d(int par1) 208 { 209 this.primaryEffect = 0; 210 211 for (int var2 = 0; var2 < this.levels && var2 < 3; ++var2) 212 { 213 Potion[] var3 = effectsList[var2]; 214 int var4 = var3.length; 215 216 for (int var5 = 0; var5 < var4; ++var5) 217 { 218 Potion var6 = var3[var5]; 219 220 if (var6.id == par1) 221 { 222 this.primaryEffect = par1; 223 return; 224 } 225 } 226 } 227 } 228 229 public void func_82127_e(int par1) 230 { 231 this.secondaryEffect = 0; 232 233 if (this.levels >= 4) 234 { 235 for (int var2 = 0; var2 < 4; ++var2) 236 { 237 Potion[] var3 = effectsList[var2]; 238 int var4 = var3.length; 239 240 for (int var5 = 0; var5 < var4; ++var5) 241 { 242 Potion var6 = var3[var5]; 243 244 if (var6.id == par1) 245 { 246 this.secondaryEffect = par1; 247 return; 248 } 249 } 250 } 251 } 252 } 253 254 /** 255 * Overriden in a sign to provide the text. 256 */ 257 public Packet getDescriptionPacket() 258 { 259 NBTTagCompound var1 = new NBTTagCompound(); 260 this.writeToNBT(var1); 261 return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 3, var1); 262 } 263 264 @SideOnly(Side.CLIENT) 265 public double func_82115_m() 266 { 267 return 65536.0D; 268 } 269 270 /** 271 * Reads a tile entity from NBT. 272 */ 273 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 274 { 275 super.readFromNBT(par1NBTTagCompound); 276 this.primaryEffect = par1NBTTagCompound.getInteger("Primary"); 277 this.secondaryEffect = par1NBTTagCompound.getInteger("Secondary"); 278 this.levels = par1NBTTagCompound.getInteger("Levels"); 279 } 280 281 /** 282 * Writes a tile entity to NBT. 283 */ 284 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 285 { 286 super.writeToNBT(par1NBTTagCompound); 287 par1NBTTagCompound.setInteger("Primary", this.primaryEffect); 288 par1NBTTagCompound.setInteger("Secondary", this.secondaryEffect); 289 par1NBTTagCompound.setInteger("Levels", this.levels); 290 } 291 292 /** 293 * Returns the number of slots in the inventory. 294 */ 295 public int getSizeInventory() 296 { 297 return 1; 298 } 299 300 /** 301 * Returns the stack in slot i 302 */ 303 public ItemStack getStackInSlot(int par1) 304 { 305 return par1 == 0 ? this.payment : null; 306 } 307 308 /** 309 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a 310 * new stack. 311 */ 312 public ItemStack decrStackSize(int par1, int par2) 313 { 314 if (par1 == 0 && this.payment != null) 315 { 316 if (par2 >= this.payment.stackSize) 317 { 318 ItemStack var3 = this.payment; 319 this.payment = null; 320 return var3; 321 } 322 else 323 { 324 this.payment.stackSize -= par2; 325 return new ItemStack(this.payment.itemID, par2, this.payment.getItemDamage()); 326 } 327 } 328 else 329 { 330 return null; 331 } 332 } 333 334 /** 335 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - 336 * like when you close a workbench GUI. 337 */ 338 public ItemStack getStackInSlotOnClosing(int par1) 339 { 340 if (par1 == 0 && this.payment != null) 341 { 342 ItemStack var2 = this.payment; 343 this.payment = null; 344 return var2; 345 } 346 else 347 { 348 return null; 349 } 350 } 351 352 /** 353 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). 354 */ 355 public void setInventorySlotContents(int par1, ItemStack par2ItemStack) 356 { 357 if (par1 == 0) 358 { 359 this.payment = par2ItemStack; 360 } 361 } 362 363 /** 364 * Returns the name of the inventory. 365 */ 366 public String getInvName() 367 { 368 return "container.beacon"; 369 } 370 371 /** 372 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't 373 * this more of a set than a get?* 374 */ 375 public int getInventoryStackLimit() 376 { 377 return 1; 378 } 379 380 /** 381 * Do not make give this method the name canInteractWith because it clashes with Container 382 */ 383 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) 384 { 385 return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D; 386 } 387 388 public void openChest() {} 389 390 public void closeChest() {} 391 }