001 package net.minecraft.entity.passive; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 import cpw.mods.fml.common.registry.VillagerRegistry; 006 007 import java.util.Collections; 008 import java.util.HashMap; 009 import java.util.Iterator; 010 import java.util.Map; 011 import java.util.Random; 012 import net.minecraft.block.Block; 013 import net.minecraft.enchantment.EnchantmentHelper; 014 import net.minecraft.entity.Entity; 015 import net.minecraft.entity.EntityAgeable; 016 import net.minecraft.entity.EntityLiving; 017 import net.minecraft.entity.IMerchant; 018 import net.minecraft.entity.INpc; 019 import net.minecraft.entity.ai.EntityAIAvoidEntity; 020 import net.minecraft.entity.ai.EntityAIFollowGolem; 021 import net.minecraft.entity.ai.EntityAILookAtTradePlayer; 022 import net.minecraft.entity.ai.EntityAIMoveIndoors; 023 import net.minecraft.entity.ai.EntityAIMoveTwardsRestriction; 024 import net.minecraft.entity.ai.EntityAIOpenDoor; 025 import net.minecraft.entity.ai.EntityAIPlay; 026 import net.minecraft.entity.ai.EntityAIRestrictOpenDoor; 027 import net.minecraft.entity.ai.EntityAISwimming; 028 import net.minecraft.entity.ai.EntityAITradePlayer; 029 import net.minecraft.entity.ai.EntityAIVillagerMate; 030 import net.minecraft.entity.ai.EntityAIWander; 031 import net.minecraft.entity.ai.EntityAIWatchClosest; 032 import net.minecraft.entity.ai.EntityAIWatchClosest2; 033 import net.minecraft.entity.monster.EntityZombie; 034 import net.minecraft.entity.monster.IMob; 035 import net.minecraft.entity.player.EntityPlayer; 036 import net.minecraft.item.Item; 037 import net.minecraft.item.ItemStack; 038 import net.minecraft.nbt.NBTTagCompound; 039 import net.minecraft.potion.Potion; 040 import net.minecraft.potion.PotionEffect; 041 import net.minecraft.util.ChunkCoordinates; 042 import net.minecraft.util.DamageSource; 043 import net.minecraft.util.MathHelper; 044 import net.minecraft.util.Tuple; 045 import net.minecraft.village.MerchantRecipe; 046 import net.minecraft.village.MerchantRecipeList; 047 import net.minecraft.village.Village; 048 import net.minecraft.world.World; 049 050 public class EntityVillager extends EntityAgeable implements INpc, IMerchant 051 { 052 private int randomTickDivider; 053 private boolean isMating; 054 private boolean isPlaying; 055 Village villageObj; 056 057 /** This villager's current customer. */ 058 private EntityPlayer buyingPlayer; 059 060 /** Initialises the MerchantRecipeList.java */ 061 private MerchantRecipeList buyingList; 062 private int timeUntilReset; 063 064 /** addDefaultEquipmentAndRecipies is called if this is true */ 065 private boolean needsInitilization; 066 private int wealth; 067 068 /** Last player to trade with this villager, used for aggressivity. */ 069 private String lastBuyingPlayer; 070 private boolean field_82190_bM; 071 private float field_82191_bN; 072 073 /** 074 * a villagers recipe list is intialized off this list ; the 2 params are min/max amount they will trade for 1 075 * emerald 076 */ 077 public static final Map villagerStockList = new HashMap(); 078 079 /** 080 * Selling list of Blacksmith items. negative numbers mean 1 emerald for n items, positive numbers are n emeralds 081 * for 1 item 082 */ 083 public static final Map blacksmithSellingList = new HashMap(); 084 085 public EntityVillager(World par1World) 086 { 087 this(par1World, 0); 088 } 089 090 public EntityVillager(World par1World, int par2) 091 { 092 super(par1World); 093 this.randomTickDivider = 0; 094 this.isMating = false; 095 this.isPlaying = false; 096 this.villageObj = null; 097 this.setProfession(par2); 098 this.texture = "/mob/villager/villager.png"; 099 this.moveSpeed = 0.5F; 100 this.getNavigator().setBreakDoors(true); 101 this.getNavigator().setAvoidsWater(true); 102 this.tasks.addTask(0, new EntityAISwimming(this)); 103 this.tasks.addTask(1, new EntityAIAvoidEntity(this, EntityZombie.class, 8.0F, 0.3F, 0.35F)); 104 this.tasks.addTask(1, new EntityAITradePlayer(this)); 105 this.tasks.addTask(1, new EntityAILookAtTradePlayer(this)); 106 this.tasks.addTask(2, new EntityAIMoveIndoors(this)); 107 this.tasks.addTask(3, new EntityAIRestrictOpenDoor(this)); 108 this.tasks.addTask(4, new EntityAIOpenDoor(this, true)); 109 this.tasks.addTask(5, new EntityAIMoveTwardsRestriction(this, 0.3F)); 110 this.tasks.addTask(6, new EntityAIVillagerMate(this)); 111 this.tasks.addTask(7, new EntityAIFollowGolem(this)); 112 this.tasks.addTask(8, new EntityAIPlay(this, 0.32F)); 113 this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityPlayer.class, 3.0F, 1.0F)); 114 this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityVillager.class, 5.0F, 0.02F)); 115 this.tasks.addTask(9, new EntityAIWander(this, 0.3F)); 116 this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F)); 117 } 118 119 /** 120 * Returns true if the newer Entity AI code should be run 121 */ 122 public boolean isAIEnabled() 123 { 124 return true; 125 } 126 127 /** 128 * main AI tick function, replaces updateEntityActionState 129 */ 130 protected void updateAITick() 131 { 132 if (--this.randomTickDivider <= 0) 133 { 134 this.worldObj.villageCollectionObj.addVillagerPosition(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)); 135 this.randomTickDivider = 70 + this.rand.nextInt(50); 136 this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32); 137 138 if (this.villageObj == null) 139 { 140 this.detachHome(); 141 } 142 else 143 { 144 ChunkCoordinates var1 = this.villageObj.getCenter(); 145 this.setHomeArea(var1.posX, var1.posY, var1.posZ, (int)((float)this.villageObj.getVillageRadius() * 0.6F)); 146 147 if (this.field_82190_bM) 148 { 149 this.field_82190_bM = false; 150 this.villageObj.func_82683_b(5); 151 } 152 } 153 } 154 155 if (!this.isTrading() && this.timeUntilReset > 0) 156 { 157 --this.timeUntilReset; 158 159 if (this.timeUntilReset <= 0) 160 { 161 if (this.needsInitilization) 162 { 163 if (this.buyingList.size() > 1) 164 { 165 Iterator var3 = this.buyingList.iterator(); 166 167 while (var3.hasNext()) 168 { 169 MerchantRecipe var2 = (MerchantRecipe)var3.next(); 170 171 if (var2.func_82784_g()) 172 { 173 var2.func_82783_a(this.rand.nextInt(6) + this.rand.nextInt(6) + 2); 174 } 175 } 176 } 177 178 this.addDefaultEquipmentAndRecipies(1); 179 this.needsInitilization = false; 180 181 if (this.villageObj != null && this.lastBuyingPlayer != null) 182 { 183 this.worldObj.setEntityState(this, (byte)14); 184 this.villageObj.setReputationForPlayer(this.lastBuyingPlayer, 1); 185 } 186 } 187 188 this.addPotionEffect(new PotionEffect(Potion.regeneration.id, 200, 0)); 189 } 190 } 191 192 super.updateAITick(); 193 } 194 195 /** 196 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. 197 */ 198 public boolean interact(EntityPlayer par1EntityPlayer) 199 { 200 ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem(); 201 boolean var3 = var2 != null && var2.itemID == Item.monsterPlacer.shiftedIndex; 202 203 if (!var3 && this.isEntityAlive() && !this.isTrading() && !this.isChild()) 204 { 205 if (!this.worldObj.isRemote) 206 { 207 this.setCustomer(par1EntityPlayer); 208 par1EntityPlayer.displayGUIMerchant(this); 209 } 210 211 return true; 212 } 213 else 214 { 215 return super.interact(par1EntityPlayer); 216 } 217 } 218 219 protected void entityInit() 220 { 221 super.entityInit(); 222 this.dataWatcher.addObject(16, Integer.valueOf(0)); 223 } 224 225 public int getMaxHealth() 226 { 227 return 20; 228 } 229 230 /** 231 * (abstract) Protected helper method to write subclass entity data to NBT. 232 */ 233 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 234 { 235 super.writeEntityToNBT(par1NBTTagCompound); 236 par1NBTTagCompound.setInteger("Profession", this.getProfession()); 237 par1NBTTagCompound.setInteger("Riches", this.wealth); 238 239 if (this.buyingList != null) 240 { 241 par1NBTTagCompound.setCompoundTag("Offers", this.buyingList.getRecipiesAsTags()); 242 } 243 } 244 245 /** 246 * (abstract) Protected helper method to read subclass entity data from NBT. 247 */ 248 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 249 { 250 super.readEntityFromNBT(par1NBTTagCompound); 251 this.setProfession(par1NBTTagCompound.getInteger("Profession")); 252 this.wealth = par1NBTTagCompound.getInteger("Riches"); 253 254 if (par1NBTTagCompound.hasKey("Offers")) 255 { 256 NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Offers"); 257 this.buyingList = new MerchantRecipeList(var2); 258 } 259 } 260 261 @SideOnly(Side.CLIENT) 262 263 /** 264 * Returns the texture's file path as a String. 265 */ 266 public String getTexture() 267 { 268 switch (this.getProfession()) 269 { 270 case 0: 271 return "/mob/villager/farmer.png"; 272 case 1: 273 return "/mob/villager/librarian.png"; 274 case 2: 275 return "/mob/villager/priest.png"; 276 case 3: 277 return "/mob/villager/smith.png"; 278 case 4: 279 return "/mob/villager/butcher.png"; 280 default: 281 return VillagerRegistry.getVillagerSkin(this.getProfession(), super.getTexture()); 282 } 283 } 284 285 /** 286 * Determines if an entity can be despawned, used on idle far away entities 287 */ 288 protected boolean canDespawn() 289 { 290 return false; 291 } 292 293 /** 294 * Returns the sound this mob makes while it's alive. 295 */ 296 protected String getLivingSound() 297 { 298 return "mob.villager.default"; 299 } 300 301 /** 302 * Returns the sound this mob makes when it is hurt. 303 */ 304 protected String getHurtSound() 305 { 306 return "mob.villager.defaulthurt"; 307 } 308 309 /** 310 * Returns the sound this mob makes on death. 311 */ 312 protected String getDeathSound() 313 { 314 return "mob.villager.defaultdeath"; 315 } 316 317 public void setProfession(int par1) 318 { 319 this.dataWatcher.updateObject(16, Integer.valueOf(par1)); 320 } 321 322 public int getProfession() 323 { 324 return this.dataWatcher.getWatchableObjectInt(16); 325 } 326 327 public boolean isMating() 328 { 329 return this.isMating; 330 } 331 332 public void setMating(boolean par1) 333 { 334 this.isMating = par1; 335 } 336 337 public void setPlaying(boolean par1) 338 { 339 this.isPlaying = par1; 340 } 341 342 public boolean isPlaying() 343 { 344 return this.isPlaying; 345 } 346 347 public void setRevengeTarget(EntityLiving par1EntityLiving) 348 { 349 super.setRevengeTarget(par1EntityLiving); 350 351 if (this.villageObj != null && par1EntityLiving != null) 352 { 353 this.villageObj.addOrRenewAgressor(par1EntityLiving); 354 355 if (par1EntityLiving instanceof EntityPlayer) 356 { 357 byte var2 = -1; 358 359 if (this.isChild()) 360 { 361 var2 = -3; 362 } 363 364 this.villageObj.setReputationForPlayer(((EntityPlayer)par1EntityLiving).getCommandSenderName(), var2); 365 366 if (this.isEntityAlive()) 367 { 368 this.worldObj.setEntityState(this, (byte)13); 369 } 370 } 371 } 372 } 373 374 /** 375 * Called when the mob's health reaches 0. 376 */ 377 public void onDeath(DamageSource par1DamageSource) 378 { 379 if (this.villageObj != null) 380 { 381 Entity var2 = par1DamageSource.getEntity(); 382 383 if (var2 != null) 384 { 385 if (var2 instanceof EntityPlayer) 386 { 387 this.villageObj.setReputationForPlayer(((EntityPlayer)var2).getCommandSenderName(), -2); 388 } 389 else if (var2 instanceof IMob) 390 { 391 this.villageObj.func_82692_h(); 392 } 393 } 394 else if (var2 == null) 395 { 396 EntityPlayer var3 = this.worldObj.getClosestPlayerToEntity(this, 16.0D); 397 398 if (var3 != null) 399 { 400 this.villageObj.func_82692_h(); 401 } 402 } 403 } 404 405 super.onDeath(par1DamageSource); 406 } 407 408 public void setCustomer(EntityPlayer par1EntityPlayer) 409 { 410 this.buyingPlayer = par1EntityPlayer; 411 } 412 413 public EntityPlayer getCustomer() 414 { 415 return this.buyingPlayer; 416 } 417 418 public boolean isTrading() 419 { 420 return this.buyingPlayer != null; 421 } 422 423 public void useRecipe(MerchantRecipe par1MerchantRecipe) 424 { 425 par1MerchantRecipe.incrementToolUses(); 426 427 if (par1MerchantRecipe.hasSameIDsAs((MerchantRecipe)this.buyingList.get(this.buyingList.size() - 1))) 428 { 429 this.timeUntilReset = 40; 430 this.needsInitilization = true; 431 432 if (this.buyingPlayer != null) 433 { 434 this.lastBuyingPlayer = this.buyingPlayer.getCommandSenderName(); 435 } 436 else 437 { 438 this.lastBuyingPlayer = null; 439 } 440 } 441 442 if (par1MerchantRecipe.getItemToBuy().itemID == Item.emerald.shiftedIndex) 443 { 444 this.wealth += par1MerchantRecipe.getItemToBuy().stackSize; 445 } 446 } 447 448 public MerchantRecipeList getRecipes(EntityPlayer par1EntityPlayer) 449 { 450 if (this.buyingList == null) 451 { 452 this.addDefaultEquipmentAndRecipies(1); 453 } 454 455 return this.buyingList; 456 } 457 458 private float func_82188_j(float par1) 459 { 460 float var2 = par1 + this.field_82191_bN; 461 return var2 > 0.9F ? 0.9F - (var2 - 0.9F) : var2; 462 } 463 464 /** 465 * based on the villagers profession add items, equipment, and recipies adds par1 random items to the list of things 466 * that the villager wants to buy. (at most 1 of each wanted type is added) 467 */ 468 private void addDefaultEquipmentAndRecipies(int par1) 469 { 470 if (this.buyingList != null) 471 { 472 this.field_82191_bN = MathHelper.sqrt_float((float)this.buyingList.size()) * 0.2F; 473 } 474 else 475 { 476 this.field_82191_bN = 0.0F; 477 } 478 479 MerchantRecipeList var2; 480 var2 = new MerchantRecipeList(); 481 VillagerRegistry.manageVillagerTrades(var2, this, this.getProfession(), this.rand); 482 label48: 483 484 switch (this.getProfession()) 485 { 486 case 0: 487 addMerchantItem(var2, Item.wheat.shiftedIndex, this.rand, this.func_82188_j(0.9F)); 488 addMerchantItem(var2, Block.cloth.blockID, this.rand, this.func_82188_j(0.5F)); 489 addMerchantItem(var2, Item.chickenRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 490 addMerchantItem(var2, Item.fishCooked.shiftedIndex, this.rand, this.func_82188_j(0.4F)); 491 addBlacksmithItem(var2, Item.bread.shiftedIndex, this.rand, this.func_82188_j(0.9F)); 492 addBlacksmithItem(var2, Item.melon.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 493 addBlacksmithItem(var2, Item.appleRed.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 494 addBlacksmithItem(var2, Item.cookie.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 495 addBlacksmithItem(var2, Item.shears.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 496 addBlacksmithItem(var2, Item.flintAndSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 497 addBlacksmithItem(var2, Item.chickenCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 498 addBlacksmithItem(var2, Item.arrow.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 499 500 if (this.rand.nextFloat() < this.func_82188_j(0.5F)) 501 { 502 var2.add(new MerchantRecipe(new ItemStack(Block.gravel, 10), new ItemStack(Item.emerald), new ItemStack(Item.flint.shiftedIndex, 4 + this.rand.nextInt(2), 0))); 503 } 504 505 break; 506 case 1: 507 addMerchantItem(var2, Item.paper.shiftedIndex, this.rand, this.func_82188_j(0.8F)); 508 addMerchantItem(var2, Item.book.shiftedIndex, this.rand, this.func_82188_j(0.8F)); 509 addMerchantItem(var2, Item.writtenBook.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 510 addBlacksmithItem(var2, Block.bookShelf.blockID, this.rand, this.func_82188_j(0.8F)); 511 addBlacksmithItem(var2, Block.glass.blockID, this.rand, this.func_82188_j(0.2F)); 512 addBlacksmithItem(var2, Item.compass.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 513 addBlacksmithItem(var2, Item.pocketSundial.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 514 break; 515 case 2: 516 addBlacksmithItem(var2, Item.eyeOfEnder.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 517 addBlacksmithItem(var2, Item.expBottle.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 518 addBlacksmithItem(var2, Item.redstone.shiftedIndex, this.rand, this.func_82188_j(0.4F)); 519 addBlacksmithItem(var2, Block.glowStone.blockID, this.rand, this.func_82188_j(0.3F)); 520 int[] var3 = new int[] {Item.swordSteel.shiftedIndex, Item.swordDiamond.shiftedIndex, Item.plateSteel.shiftedIndex, Item.plateDiamond.shiftedIndex, Item.axeSteel.shiftedIndex, Item.axeDiamond.shiftedIndex, Item.pickaxeSteel.shiftedIndex, Item.pickaxeDiamond.shiftedIndex}; 521 int[] var4 = var3; 522 int var5 = var3.length; 523 int var6 = 0; 524 525 while (true) 526 { 527 if (var6 >= var5) 528 { 529 break label48; 530 } 531 532 int var7 = var4[var6]; 533 534 if (this.rand.nextFloat() < this.func_82188_j(0.05F)) 535 { 536 var2.add(new MerchantRecipe(new ItemStack(var7, 1, 0), new ItemStack(Item.emerald, 2 + this.rand.nextInt(3), 0), EnchantmentHelper.addRandomEnchantment(this.rand, new ItemStack(var7, 1, 0), 5 + this.rand.nextInt(15)))); 537 } 538 539 ++var6; 540 } 541 case 3: 542 addMerchantItem(var2, Item.coal.shiftedIndex, this.rand, this.func_82188_j(0.7F)); 543 addMerchantItem(var2, Item.ingotIron.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 544 addMerchantItem(var2, Item.ingotGold.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 545 addMerchantItem(var2, Item.diamond.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 546 addBlacksmithItem(var2, Item.swordSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 547 addBlacksmithItem(var2, Item.swordDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 548 addBlacksmithItem(var2, Item.axeSteel.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 549 addBlacksmithItem(var2, Item.axeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 550 addBlacksmithItem(var2, Item.pickaxeSteel.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 551 addBlacksmithItem(var2, Item.pickaxeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 552 addBlacksmithItem(var2, Item.shovelSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 553 addBlacksmithItem(var2, Item.shovelDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 554 addBlacksmithItem(var2, Item.hoeSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 555 addBlacksmithItem(var2, Item.hoeDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 556 addBlacksmithItem(var2, Item.bootsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 557 addBlacksmithItem(var2, Item.bootsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 558 addBlacksmithItem(var2, Item.helmetSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 559 addBlacksmithItem(var2, Item.helmetDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 560 addBlacksmithItem(var2, Item.plateSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 561 addBlacksmithItem(var2, Item.plateDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 562 addBlacksmithItem(var2, Item.legsSteel.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 563 addBlacksmithItem(var2, Item.legsDiamond.shiftedIndex, this.rand, this.func_82188_j(0.2F)); 564 addBlacksmithItem(var2, Item.bootsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F)); 565 addBlacksmithItem(var2, Item.helmetChain.shiftedIndex, this.rand, this.func_82188_j(0.1F)); 566 addBlacksmithItem(var2, Item.plateChain.shiftedIndex, this.rand, this.func_82188_j(0.1F)); 567 addBlacksmithItem(var2, Item.legsChain.shiftedIndex, this.rand, this.func_82188_j(0.1F)); 568 break; 569 case 4: 570 addMerchantItem(var2, Item.coal.shiftedIndex, this.rand, this.func_82188_j(0.7F)); 571 addMerchantItem(var2, Item.porkRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 572 addMerchantItem(var2, Item.beefRaw.shiftedIndex, this.rand, this.func_82188_j(0.5F)); 573 addBlacksmithItem(var2, Item.saddle.shiftedIndex, this.rand, this.func_82188_j(0.1F)); 574 addBlacksmithItem(var2, Item.plateLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 575 addBlacksmithItem(var2, Item.bootsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 576 addBlacksmithItem(var2, Item.helmetLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 577 addBlacksmithItem(var2, Item.legsLeather.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 578 addBlacksmithItem(var2, Item.porkCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 579 addBlacksmithItem(var2, Item.beefCooked.shiftedIndex, this.rand, this.func_82188_j(0.3F)); 580 } 581 582 if (var2.isEmpty()) 583 { 584 addMerchantItem(var2, Item.ingotGold.shiftedIndex, this.rand, 1.0F); 585 } 586 587 Collections.shuffle(var2); 588 589 if (this.buyingList == null) 590 { 591 this.buyingList = new MerchantRecipeList(); 592 } 593 594 for (int var8 = 0; var8 < par1 && var8 < var2.size(); ++var8) 595 { 596 this.buyingList.addToListWithCheck((MerchantRecipe)var2.get(var8)); 597 } 598 } 599 600 @SideOnly(Side.CLIENT) 601 public void setRecipes(MerchantRecipeList par1MerchantRecipeList) {} 602 603 /** 604 * each recipie takes a random stack from villagerStockList and offers it for 1 emerald 605 */ 606 public static void addMerchantItem(MerchantRecipeList par0MerchantRecipeList, int par1, Random par2Random, float par3) 607 { 608 if (par2Random.nextFloat() < par3) 609 { 610 par0MerchantRecipeList.add(new MerchantRecipe(getRandomSizedStack(par1, par2Random), Item.emerald)); 611 } 612 } 613 614 private static ItemStack getRandomSizedStack(int par0, Random par1Random) 615 { 616 return new ItemStack(par0, getRandomCountForItem(par0, par1Random), 0); 617 } 618 619 /** 620 * default to 1, and villagerStockList contains a min/max amount for each index 621 */ 622 private static int getRandomCountForItem(int par0, Random par1Random) 623 { 624 Tuple var2 = (Tuple)villagerStockList.get(Integer.valueOf(par0)); 625 return var2 == null ? 1 : (((Integer)var2.getFirst()).intValue() >= ((Integer)var2.getSecond()).intValue() ? ((Integer)var2.getFirst()).intValue() : ((Integer)var2.getFirst()).intValue() + par1Random.nextInt(((Integer)var2.getSecond()).intValue() - ((Integer)var2.getFirst()).intValue())); 626 } 627 628 public static void addBlacksmithItem(MerchantRecipeList par0MerchantRecipeList, int par1, Random par2Random, float par3) 629 { 630 if (par2Random.nextFloat() < par3) 631 { 632 int var4 = getRandomCountForBlacksmithItem(par1, par2Random); 633 ItemStack var5; 634 ItemStack var6; 635 636 if (var4 < 0) 637 { 638 var5 = new ItemStack(Item.emerald.shiftedIndex, 1, 0); 639 var6 = new ItemStack(par1, -var4, 0); 640 } 641 else 642 { 643 var5 = new ItemStack(Item.emerald.shiftedIndex, var4, 0); 644 var6 = new ItemStack(par1, 1, 0); 645 } 646 647 par0MerchantRecipeList.add(new MerchantRecipe(var5, var6)); 648 } 649 } 650 651 private static int getRandomCountForBlacksmithItem(int par0, Random par1Random) 652 { 653 Tuple var2 = (Tuple)blacksmithSellingList.get(Integer.valueOf(par0)); 654 return var2 == null ? 1 : (((Integer)var2.getFirst()).intValue() >= ((Integer)var2.getSecond()).intValue() ? ((Integer)var2.getFirst()).intValue() : ((Integer)var2.getFirst()).intValue() + par1Random.nextInt(((Integer)var2.getSecond()).intValue() - ((Integer)var2.getFirst()).intValue())); 655 } 656 657 @SideOnly(Side.CLIENT) 658 public void handleHealthUpdate(byte par1) 659 { 660 if (par1 == 12) 661 { 662 this.generateRandomParticles("heart"); 663 } 664 else if (par1 == 13) 665 { 666 this.generateRandomParticles("angryVillager"); 667 } 668 else if (par1 == 14) 669 { 670 this.generateRandomParticles("happyVillager"); 671 } 672 else 673 { 674 super.handleHealthUpdate(par1); 675 } 676 } 677 678 @SideOnly(Side.CLIENT) 679 680 /** 681 * par1 is the particleName 682 */ 683 private void generateRandomParticles(String par1Str) 684 { 685 for (int var2 = 0; var2 < 5; ++var2) 686 { 687 double var3 = this.rand.nextGaussian() * 0.02D; 688 double var5 = this.rand.nextGaussian() * 0.02D; 689 double var7 = this.rand.nextGaussian() * 0.02D; 690 this.worldObj.spawnParticle(par1Str, this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 1.0D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, var3, var5, var7); 691 } 692 } 693 694 /** 695 * Initialize this creature. 696 */ 697 public void initCreature() 698 { 699 VillagerRegistry.applyRandomTrade(this, worldObj.rand); 700 } 701 702 public void func_82187_q() 703 { 704 this.field_82190_bM = true; 705 } 706 707 public EntityVillager func_90012_b(EntityAgeable par1EntityAgeable) 708 { 709 EntityVillager var2 = new EntityVillager(this.worldObj); 710 var2.initCreature(); 711 return var2; 712 } 713 714 public EntityAgeable func_90011_a(EntityAgeable par1EntityAgeable) 715 { 716 return this.func_90012_b(par1EntityAgeable); 717 } 718 719 static 720 { 721 villagerStockList.put(Integer.valueOf(Item.coal.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(24))); 722 villagerStockList.put(Integer.valueOf(Item.ingotIron.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10))); 723 villagerStockList.put(Integer.valueOf(Item.ingotGold.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10))); 724 villagerStockList.put(Integer.valueOf(Item.diamond.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6))); 725 villagerStockList.put(Integer.valueOf(Item.paper.shiftedIndex), new Tuple(Integer.valueOf(24), Integer.valueOf(36))); 726 villagerStockList.put(Integer.valueOf(Item.book.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(13))); 727 villagerStockList.put(Integer.valueOf(Item.writtenBook.shiftedIndex), new Tuple(Integer.valueOf(1), Integer.valueOf(1))); 728 villagerStockList.put(Integer.valueOf(Item.enderPearl.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4))); 729 villagerStockList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(3))); 730 villagerStockList.put(Integer.valueOf(Item.porkRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18))); 731 villagerStockList.put(Integer.valueOf(Item.beefRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18))); 732 villagerStockList.put(Integer.valueOf(Item.chickenRaw.shiftedIndex), new Tuple(Integer.valueOf(14), Integer.valueOf(18))); 733 villagerStockList.put(Integer.valueOf(Item.fishCooked.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(13))); 734 villagerStockList.put(Integer.valueOf(Item.seeds.shiftedIndex), new Tuple(Integer.valueOf(34), Integer.valueOf(48))); 735 villagerStockList.put(Integer.valueOf(Item.melonSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38))); 736 villagerStockList.put(Integer.valueOf(Item.pumpkinSeeds.shiftedIndex), new Tuple(Integer.valueOf(30), Integer.valueOf(38))); 737 villagerStockList.put(Integer.valueOf(Item.wheat.shiftedIndex), new Tuple(Integer.valueOf(18), Integer.valueOf(22))); 738 villagerStockList.put(Integer.valueOf(Block.cloth.blockID), new Tuple(Integer.valueOf(14), Integer.valueOf(22))); 739 villagerStockList.put(Integer.valueOf(Item.rottenFlesh.shiftedIndex), new Tuple(Integer.valueOf(36), Integer.valueOf(64))); 740 blacksmithSellingList.put(Integer.valueOf(Item.flintAndSteel.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4))); 741 blacksmithSellingList.put(Integer.valueOf(Item.shears.shiftedIndex), new Tuple(Integer.valueOf(3), Integer.valueOf(4))); 742 blacksmithSellingList.put(Integer.valueOf(Item.swordSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11))); 743 blacksmithSellingList.put(Integer.valueOf(Item.swordDiamond.shiftedIndex), new Tuple(Integer.valueOf(12), Integer.valueOf(14))); 744 blacksmithSellingList.put(Integer.valueOf(Item.axeSteel.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8))); 745 blacksmithSellingList.put(Integer.valueOf(Item.axeDiamond.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(12))); 746 blacksmithSellingList.put(Integer.valueOf(Item.pickaxeSteel.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(9))); 747 blacksmithSellingList.put(Integer.valueOf(Item.pickaxeDiamond.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12))); 748 blacksmithSellingList.put(Integer.valueOf(Item.shovelSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6))); 749 blacksmithSellingList.put(Integer.valueOf(Item.shovelDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8))); 750 blacksmithSellingList.put(Integer.valueOf(Item.hoeSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6))); 751 blacksmithSellingList.put(Integer.valueOf(Item.hoeDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8))); 752 blacksmithSellingList.put(Integer.valueOf(Item.bootsSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6))); 753 blacksmithSellingList.put(Integer.valueOf(Item.bootsDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8))); 754 blacksmithSellingList.put(Integer.valueOf(Item.helmetSteel.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(6))); 755 blacksmithSellingList.put(Integer.valueOf(Item.helmetDiamond.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(8))); 756 blacksmithSellingList.put(Integer.valueOf(Item.plateSteel.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(14))); 757 blacksmithSellingList.put(Integer.valueOf(Item.plateDiamond.shiftedIndex), new Tuple(Integer.valueOf(16), Integer.valueOf(19))); 758 blacksmithSellingList.put(Integer.valueOf(Item.legsSteel.shiftedIndex), new Tuple(Integer.valueOf(8), Integer.valueOf(10))); 759 blacksmithSellingList.put(Integer.valueOf(Item.legsDiamond.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(14))); 760 blacksmithSellingList.put(Integer.valueOf(Item.bootsChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7))); 761 blacksmithSellingList.put(Integer.valueOf(Item.helmetChain.shiftedIndex), new Tuple(Integer.valueOf(5), Integer.valueOf(7))); 762 blacksmithSellingList.put(Integer.valueOf(Item.plateChain.shiftedIndex), new Tuple(Integer.valueOf(11), Integer.valueOf(15))); 763 blacksmithSellingList.put(Integer.valueOf(Item.legsChain.shiftedIndex), new Tuple(Integer.valueOf(9), Integer.valueOf(11))); 764 blacksmithSellingList.put(Integer.valueOf(Item.bread.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-2))); 765 blacksmithSellingList.put(Integer.valueOf(Item.melon.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4))); 766 blacksmithSellingList.put(Integer.valueOf(Item.appleRed.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-4))); 767 blacksmithSellingList.put(Integer.valueOf(Item.cookie.shiftedIndex), new Tuple(Integer.valueOf(-10), Integer.valueOf(-7))); 768 blacksmithSellingList.put(Integer.valueOf(Block.glass.blockID), new Tuple(Integer.valueOf(-5), Integer.valueOf(-3))); 769 blacksmithSellingList.put(Integer.valueOf(Block.bookShelf.blockID), new Tuple(Integer.valueOf(3), Integer.valueOf(4))); 770 blacksmithSellingList.put(Integer.valueOf(Item.plateLeather.shiftedIndex), new Tuple(Integer.valueOf(4), Integer.valueOf(5))); 771 blacksmithSellingList.put(Integer.valueOf(Item.bootsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4))); 772 blacksmithSellingList.put(Integer.valueOf(Item.helmetLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4))); 773 blacksmithSellingList.put(Integer.valueOf(Item.legsLeather.shiftedIndex), new Tuple(Integer.valueOf(2), Integer.valueOf(4))); 774 blacksmithSellingList.put(Integer.valueOf(Item.saddle.shiftedIndex), new Tuple(Integer.valueOf(6), Integer.valueOf(8))); 775 blacksmithSellingList.put(Integer.valueOf(Item.expBottle.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1))); 776 blacksmithSellingList.put(Integer.valueOf(Item.redstone.shiftedIndex), new Tuple(Integer.valueOf(-4), Integer.valueOf(-1))); 777 blacksmithSellingList.put(Integer.valueOf(Item.compass.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12))); 778 blacksmithSellingList.put(Integer.valueOf(Item.pocketSundial.shiftedIndex), new Tuple(Integer.valueOf(10), Integer.valueOf(12))); 779 blacksmithSellingList.put(Integer.valueOf(Block.glowStone.blockID), new Tuple(Integer.valueOf(-3), Integer.valueOf(-1))); 780 blacksmithSellingList.put(Integer.valueOf(Item.porkCooked.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5))); 781 blacksmithSellingList.put(Integer.valueOf(Item.beefCooked.shiftedIndex), new Tuple(Integer.valueOf(-7), Integer.valueOf(-5))); 782 blacksmithSellingList.put(Integer.valueOf(Item.chickenCooked.shiftedIndex), new Tuple(Integer.valueOf(-8), Integer.valueOf(-6))); 783 blacksmithSellingList.put(Integer.valueOf(Item.eyeOfEnder.shiftedIndex), new Tuple(Integer.valueOf(7), Integer.valueOf(11))); 784 blacksmithSellingList.put(Integer.valueOf(Item.arrow.shiftedIndex), new Tuple(Integer.valueOf(-12), Integer.valueOf(-8))); 785 } 786 }