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