Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemHandler.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 #include "ItemHandler.h"
4 #include "../World.h"
5 #include "../Entities/Player.h"
6 #include "../FastRandom.h"
7 #include "../BlockInServerPluginInterface.h"
8 #include "../Chunk.h"
9 
10 // Handlers:
11 #include "ItemArmor.h"
12 #include "ItemBed.h"
13 #include "ItemBigFlower.h"
14 #include "ItemBoat.h"
15 #include "ItemBottle.h"
16 #include "ItemBow.h"
17 #include "ItemBrewingStand.h"
18 #include "ItemBucket.h"
19 #include "ItemCake.h"
20 #include "ItemCauldron.h"
21 #include "ItemChest.h"
22 #include "ItemCloth.h"
23 #include "ItemComparator.h"
24 #include "ItemDoor.h"
25 #include "ItemDye.h"
26 #include "ItemEmptyMap.h"
27 #include "ItemEyeOfEnder.h"
28 #include "ItemFishingRod.h"
29 #include "ItemFlowerPot.h"
30 #include "ItemFood.h"
31 #include "ItemGoldenApple.h"
32 #include "ItemHoe.h"
33 #include "ItemItemFrame.h"
34 #include "ItemLeaves.h"
35 #include "ItemLighter.h"
36 #include "ItemLilypad.h"
37 #include "ItemMap.h"
38 #include "ItemMilk.h"
39 #include "ItemMinecart.h"
40 #include "ItemMobHead.h"
41 #include "ItemNetherWart.h"
42 #include "ItemPainting.h"
43 #include "ItemPickaxe.h"
44 #include "ItemPotion.h"
45 #include "ItemPumpkin.h"
46 #include "ItemRedstoneDust.h"
47 #include "ItemRedstoneRepeater.h"
48 #include "ItemSapling.h"
49 #include "ItemSeeds.h"
50 #include "ItemShears.h"
51 #include "ItemShovel.h"
52 #include "ItemSign.h"
53 #include "ItemSlab.h"
54 #include "ItemSpawnEgg.h"
55 #include "ItemString.h"
56 #include "ItemSugarcane.h"
57 #include "ItemSword.h"
58 #include "ItemThrowable.h"
59 #include "ItemAxe.h"
60 
61 #include "../Blocks/BlockHandler.h"
62 
63 
64 
65 
66 
69 
70 
71 
72 
73 
75 {
76  if ((a_ItemType < 0) || (static_cast<size_t>(a_ItemType) >= ARRAYCOUNT(m_ItemHandler)))
77  {
78  // Either nothing (-1), or bad value, both cases should return the air handler
79  if (a_ItemType < -1)
80  {
81  ASSERT(!"Bad item type");
82  }
83  a_ItemType = 0;
84  }
85 
87  {
88  // We need to initialize
89  memset(m_ItemHandler, 0, sizeof(m_ItemHandler));
90  m_HandlerInitialized = true;
91  }
92  if (m_ItemHandler[a_ItemType] == nullptr)
93  {
94  m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
95  }
96  return m_ItemHandler[a_ItemType];
97 }
98 
99 
100 
101 
102 
104 {
105  switch (a_ItemType)
106  {
107  default: return new cItemHandler(a_ItemType);
108 
109  // Single item per handler, alphabetically sorted:
110  case E_BLOCK_BIG_FLOWER: return new cItemBigFlowerHandler;
111  case E_BLOCK_CHEST: return new cItemChestHandler(a_ItemType);
112  case E_BLOCK_LEAVES: return new cItemLeavesHandler(a_ItemType);
113  case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType);
114  case E_BLOCK_HEAD: return new cItemMobHeadHandler(a_ItemType);
115  case E_BLOCK_NEW_LEAVES: return new cItemLeavesHandler(a_ItemType);
116  case E_BLOCK_PUMPKIN: return new cItemPumpkinHandler;
119  case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType);
121  case E_BLOCK_TRAPPED_CHEST: return new cItemChestHandler(a_ItemType);
123  case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType);
124  case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
126  case E_ITEM_BOW: return new cItemBowHandler();
127  case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
128  case E_ITEM_CAKE: return new cItemCakeHandler(a_ItemType);
129  case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
130  case E_ITEM_COMPARATOR: return new cItemComparatorHandler(a_ItemType);
131  case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
132  case E_ITEM_EGG: return new cItemEggHandler();
133  case E_ITEM_EMPTY_MAP: return new cItemEmptyMapHandler();
134  case E_ITEM_ENDER_PEARL: return new cItemEnderPearlHandler();
135  case E_ITEM_EYE_OF_ENDER: return new cItemEyeOfEnderHandler();
136  case E_ITEM_FIRE_CHARGE: return new cItemLighterHandler(a_ItemType);
137  case E_ITEM_FIREWORK_ROCKET: return new cItemFireworkHandler();
138  case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType);
139  case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
140  case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
141  case E_ITEM_GLASS_BOTTLE: return new cItemBottleHandler();
142  case E_ITEM_GOLDEN_APPLE: return new cItemGoldenAppleHandler();
143  case E_ITEM_MAP: return new cItemMapHandler();
144  case E_ITEM_MILK: return new cItemMilkHandler();
145  case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType);
146  case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType);
147  case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType);
148  case E_ITEM_POTIONS: return new cItemPotionHandler();
149  case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
150  case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
151  case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
152  case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType);
153  case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType);
154  case E_ITEM_SNOWBALL: return new cItemSnowballHandler();
155  case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
156  case E_ITEM_STRING: return new cItemStringHandler(a_ItemType);
157  case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);
158 
159  case E_ITEM_WOODEN_HOE:
160  case E_ITEM_STONE_HOE:
161  case E_ITEM_IRON_HOE:
162  case E_ITEM_GOLD_HOE:
163  case E_ITEM_DIAMOND_HOE:
164  {
165  return new cItemHoeHandler(a_ItemType);
166  }
167 
170  case E_ITEM_IRON_PICKAXE:
171  case E_ITEM_GOLD_PICKAXE:
173  {
174  return new cItemPickaxeHandler(a_ItemType);
175  }
176 
178  case E_ITEM_STONE_SHOVEL:
179  case E_ITEM_IRON_SHOVEL:
180  case E_ITEM_GOLD_SHOVEL:
182  {
183  return new cItemShovelHandler(a_ItemType);
184  }
185 
186  case E_ITEM_WOODEN_AXE:
187  case E_ITEM_STONE_AXE:
188  case E_ITEM_IRON_AXE:
189  case E_ITEM_GOLD_AXE:
190  case E_ITEM_DIAMOND_AXE:
191  {
192  return new cItemAxeHandler(a_ItemType);
193  }
194 
195  case E_ITEM_WOODEN_SWORD:
196  case E_ITEM_STONE_SWORD:
197  case E_ITEM_IRON_SWORD:
198  case E_ITEM_GOLD_SWORD:
200  {
201  return new cItemSwordHandler(a_ItemType);
202  }
203 
204  case E_ITEM_BUCKET:
205  case E_ITEM_WATER_BUCKET:
206  case E_ITEM_LAVA_BUCKET:
207  {
208  return new cItemBucketHandler(a_ItemType);
209  }
210 
212  case E_ITEM_CARROT:
213  case E_ITEM_MELON_SEEDS:
214  case E_ITEM_POTATO:
216  case E_ITEM_SEEDS:
217  {
218  return new cItemSeedsHandler(a_ItemType);
219  }
220 
221  case E_ITEM_ACACIA_DOOR:
222  case E_ITEM_BIRCH_DOOR:
224  case E_ITEM_JUNGLE_DOOR:
225  case E_ITEM_SPRUCE_DOOR:
226  case E_ITEM_IRON_DOOR:
227  case E_ITEM_WOODEN_DOOR:
228  {
229  return new cItemDoorHandler(a_ItemType);
230  }
231 
232  case E_ITEM_MINECART:
237  {
238  return new cItemMinecartHandler(a_ItemType);
239  }
240 
241  // Food (please keep alpha-sorted):
242  // (carrots and potatoes handled separately in SeedHandler as they're both seed and food)
243  case E_ITEM_BAKED_POTATO:
244  case E_ITEM_BEETROOT:
246  case E_ITEM_BREAD:
247  case E_ITEM_CHORUS_FRUIT:
249  case E_ITEM_COOKED_FISH:
253  case E_ITEM_COOKIE:
255  case E_ITEM_MELON_SLICE:
258  case E_ITEM_PUMPKIN_PIE:
259  case E_ITEM_RABBIT_STEW:
260  case E_ITEM_RAW_BEEF:
261  case E_ITEM_RAW_CHICKEN:
262  case E_ITEM_RAW_FISH:
263  case E_ITEM_RAW_MUTTON:
264  case E_ITEM_RAW_PORKCHOP:
265  case E_ITEM_RAW_RABBIT:
266  case E_ITEM_RED_APPLE:
267  case E_ITEM_ROTTEN_FLESH:
268  case E_ITEM_SPIDER_EYE:
269  case E_ITEM_STEAK:
270  {
271  return new cItemFoodHandler(a_ItemType);
272  }
273 
274  // Armor:
275  case E_ITEM_LEATHER_CAP:
276  case E_ITEM_GOLD_HELMET:
277  case E_ITEM_CHAIN_HELMET:
278  case E_ITEM_IRON_HELMET:
291  case E_ITEM_GOLD_BOOTS:
292  case E_ITEM_CHAIN_BOOTS:
293  case E_ITEM_IRON_BOOTS:
295  {
296  return new cItemArmorHandler(a_ItemType);
297  }
298 
299  case E_ITEM_ACACIA_BOAT:
300  case E_ITEM_BIRCH_BOAT:
301  case E_ITEM_BOAT:
303  case E_ITEM_JUNGLE_BOAT:
304  case E_ITEM_SPRUCE_BOAT:
305  {
306  return new cItemBoatHandler(a_ItemType);
307  }
308  }
309 }
310 
311 
312 
313 
314 
316 {
317  for (size_t i = 0; i < ARRAYCOUNT(m_ItemHandler); i++)
318  {
319  delete m_ItemHandler[i];
320  m_ItemHandler[i] = nullptr;
321  }
322  memset(m_ItemHandler, 0, sizeof(m_ItemHandler)); // Don't leave any dangling pointers around, just in case
323  m_HandlerInitialized = false;
324 }
325 
326 
327 
328 
329 
331 {
332  m_ItemType = a_ItemType;
333 }
334 
335 
336 
337 
338 
340  cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
341  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
342  int a_CursorX, int a_CursorY, int a_CursorZ
343 )
344 {
345  if (a_BlockFace < 0)
346  {
347  // Clicked in air
348  return false;
349  }
350 
351  if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
352  {
353  // The clicked block is outside the world, ignore this call altogether (#128)
354  return false;
355  }
356 
357  BLOCKTYPE ClickedBlock;
358  NIBBLETYPE ClickedBlockMeta;
359 
360  a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
361  cChunkInterface ChunkInterface(a_World.GetChunkMap());
362 
363  // Check if the block ignores build collision (water, grass etc.):
364  auto blockHandler = BlockHandler(ClickedBlock);
365  Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ);
366  if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, absPos, a_Player, ClickedBlockMeta))
367  {
368  a_World.DropBlockAsPickups(absPos, &a_Player, nullptr);
369  }
370  else
371  {
372  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
373 
374  if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
375  {
376  // The block is being placed outside the world, ignore this packet altogether (#128)
377  return false;
378  }
379 
380  NIBBLETYPE PlaceMeta;
381  BLOCKTYPE PlaceBlock;
382  a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta);
383 
384  // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
385  // No need to do combinability (dblslab) checks, client will do that here.
386  if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(ChunkInterface, { a_BlockX, a_BlockY, a_BlockZ }, a_Player, PlaceMeta))
387  {
388  // Tried to place a block into another?
389  // Happens when you place a block aiming at side of block with a torch on it or stem beside it
390  return false;
391  }
392  }
393 
394  // Get all the blocks to place:
395  sSetBlockVector blocks;
396  if (!GetBlocksToPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, blocks))
397  {
398  // Handler refused the placement, send that information back to the client:
399  for (const auto & blk: blocks)
400  {
401  a_World.SendBlockTo(blk.GetX(), blk.GetY(), blk.GetZ(), a_Player);
402  }
403  a_World.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
404  a_Player.GetInventory().SendEquippedSlot();
405  return false;
406  }
407 
408  // Try to place the blocks:
409  if (!a_Player.PlaceBlocks(blocks))
410  {
411  // The placement failed, the blocks have already been re-sent, re-send inventory:
412  a_Player.GetInventory().SendEquippedSlot();
413  return false;
414  }
415 
416  // Remove the "placed" item:
417  if (a_Player.IsGameModeSurvival())
418  {
419  a_Player.GetInventory().RemoveOneEquippedItem();
420  }
421  return true;
422 }
423 
424 
425 
426 
427 
429  cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
430  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
431  int a_CursorX, int a_CursorY, int a_CursorZ,
432  sSetBlockVector & a_BlocksToSet
433 )
434 {
435  BLOCKTYPE BlockType;
436  NIBBLETYPE BlockMeta;
437  if (!GetPlacementBlockTypeMeta(&a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
438  {
439  return false;
440  }
441  a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
442  return true;
443 }
444 
445 
446 
447 
448 
450  cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
451  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
452 )
453 {
454  UNUSED(a_World);
455  UNUSED(a_Player);
456  UNUSED(a_PluginInterface);
457  UNUSED(a_Item);
458  UNUSED(a_BlockX);
459  UNUSED(a_BlockY);
460  UNUSED(a_BlockZ);
461  UNUSED(a_BlockFace);
462 
463  return false;
464 }
465 
466 
467 
468 
469 
470 bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir)
471 {
472  UNUSED(a_World);
473  UNUSED(a_Player);
474  UNUSED(a_Item);
475  UNUSED(a_BlockX);
476  UNUSED(a_BlockY);
477  UNUSED(a_BlockZ);
478  UNUSED(a_Dir);
479 
480  return false;
481 }
482 
483 
484 
485 
486 
487 void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity)
488 {
489  UNUSED(a_AttackedEntity);
490  a_Attacker->UseEquippedItem(dlaAttackEntity);
491 }
492 
493 
494 
495 
496 
497 void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_Item)
498 {
499  UNUSED(a_World);
500  UNUSED(a_Player);
501  UNUSED(a_Item);
502 }
503 
504 
505 
506 
507 
509 {
510  UNUSED(a_Action);
511 
512  return 0;
513 }
514 
515 
516 
517 
518 
520 {
521  if (m_ItemType < 256)
522  {
523  // All blocks can stack up to 64
524  return 64;
525  }
526 
527  switch (m_ItemType)
528  {
529  case E_ITEM_ACACIA_DOOR: return 64;
530  case E_ITEM_ARMOR_STAND: return 16;
531  case E_ITEM_ARROW: return 64;
532  case E_ITEM_BAKED_POTATO: return 64;
533  case E_ITEM_BANNER: return 16;
534  case E_ITEM_BEETROOT: return 64;
535  case E_ITEM_BEETROOT_SEEDS: return 64;
536  case E_ITEM_BIRCH_DOOR: return 64;
537  case E_ITEM_BLAZE_POWDER: return 64;
538  case E_ITEM_BLAZE_ROD: return 64;
539  case E_ITEM_BONE: return 64;
540  case E_ITEM_BOOK: return 64;
541  case E_ITEM_BOTTLE_O_ENCHANTING: return 64;
542  case E_ITEM_BOWL: return 64;
543  case E_ITEM_BREAD: return 64;
544  case E_ITEM_BREWING_STAND: return 64;
545  case E_ITEM_BUCKET: return 16;
546  case E_ITEM_CARROT: return 64;
547  case E_ITEM_CAULDRON: return 64;
548  case E_ITEM_CHORUS_FRUIT: return 64;
549  case E_ITEM_CLAY: return 64;
550  case E_ITEM_CLAY_BRICK: return 64;
551  case E_ITEM_CLOCK: return 64;
552  case E_ITEM_COAL: return 64;
553  case E_ITEM_COMPARATOR: return 64;
554  case E_ITEM_COMPASS: return 64;
555  case E_ITEM_COOKED_CHICKEN: return 64;
556  case E_ITEM_COOKED_FISH: return 64;
557  case E_ITEM_COOKED_MUTTON: return 64;
558  case E_ITEM_COOKED_PORKCHOP: return 64;
559  case E_ITEM_COOKED_RABBIT: return 64;
560  case E_ITEM_COOKIE: return 64;
561  case E_ITEM_DARK_OAK_DOOR: return 64;
562  case E_ITEM_DIAMOND: return 64;
563  case E_ITEM_DRAGON_BREATH: return 64;
564  case E_ITEM_DYE: return 64;
565  case E_ITEM_EGG: return 16;
566  case E_ITEM_EMERALD: return 64;
567  case E_ITEM_EMPTY_MAP: return 64;
568  case E_ITEM_ENDER_PEARL: return 16;
569  case E_ITEM_EYE_OF_ENDER: return 64;
570  case E_ITEM_FEATHER: return 64;
571  case E_ITEM_FERMENTED_SPIDER_EYE: return 64;
572  case E_ITEM_FIRE_CHARGE: return 64;
573  case E_ITEM_FIREWORK_ROCKET: return 64;
574  case E_ITEM_FIREWORK_STAR: return 64;
575  case E_ITEM_FLINT: return 64;
576  case E_ITEM_FLOWER_POT: return 64;
577  case E_ITEM_GHAST_TEAR: return 64;
578  case E_ITEM_GLASS_BOTTLE: return 64;
579  case E_ITEM_GLISTERING_MELON: return 64;
580  case E_ITEM_GLOWSTONE_DUST: return 64;
581  case E_ITEM_GOLD: return 64;
582  case E_ITEM_GOLDEN_APPLE: return 64;
583  case E_ITEM_GOLDEN_CARROT: return 64;
584  case E_ITEM_GOLD_NUGGET: return 64;
585  case E_ITEM_GUNPOWDER: return 64;
586  case E_ITEM_HEAD: return 64;
587  case E_ITEM_JUNGLE_DOOR: return 64;
588  case E_ITEM_IRON: return 64;
589  case E_ITEM_IRON_DOOR: return 64;
590  case E_ITEM_IRON_NUGGET: return 64;
591  case E_ITEM_ITEM_FRAME: return 64;
592  case E_ITEM_LEAD: return 64;
593  case E_ITEM_LEATHER: return 64;
594  case E_ITEM_MAGMA_CREAM: return 64;
595  case E_ITEM_MAP: return 64;
596  case E_ITEM_MELON_SEEDS: return 64;
597  case E_ITEM_MELON_SLICE: return 64;
598  case E_ITEM_NETHER_BRICK: return 64;
599  case E_ITEM_NETHER_QUARTZ: return 64;
600  case E_ITEM_NETHER_WART: return 64;
601  case E_ITEM_PAINTING: return 64;
602  case E_ITEM_PAPER: return 64;
603  case E_ITEM_POISONOUS_POTATO: return 64;
604  case E_ITEM_POPPED_CHORUS_FRUIT: return 64;
605  case E_ITEM_POTATO: return 64;
606  case E_ITEM_PRISMARINE_CRYSTALS: return 64;
607  case E_ITEM_PRISMARINE_SHARD: return 64;
608  case E_ITEM_PUMPKIN_PIE: return 64;
609  case E_ITEM_PUMPKIN_SEEDS: return 64;
610  case E_ITEM_RABBITS_FOOT: return 64;
611  case E_ITEM_RABBIT_HIDE: return 64;
612  case E_ITEM_RAW_BEEF: return 64;
613  case E_ITEM_RAW_CHICKEN: return 64;
614  case E_ITEM_RAW_FISH: return 64;
615  case E_ITEM_RAW_MUTTON: return 64;
616  case E_ITEM_RAW_PORKCHOP: return 64;
617  case E_ITEM_RAW_RABBIT: return 64;
618  case E_ITEM_RED_APPLE: return 64;
619  case E_ITEM_REDSTONE_DUST: return 64;
620  case E_ITEM_REDSTONE_REPEATER: return 64;
621  case E_ITEM_ROTTEN_FLESH: return 64;
622  case E_ITEM_SEEDS: return 64;
623  case E_ITEM_SIGN: return 16;
624  case E_ITEM_SLIMEBALL: return 64;
625  case E_ITEM_SNOWBALL: return 16;
626  case E_ITEM_SPAWN_EGG: return 64;
627  case E_ITEM_SPECTRAL_ARROW: return 64;
628  case E_ITEM_SPIDER_EYE: return 64;
629  case E_ITEM_SPRUCE_DOOR: return 64;
630  case E_ITEM_STEAK: return 64;
631  case E_ITEM_STICK: return 64;
632  case E_ITEM_STRING: return 64;
633  case E_ITEM_SUGAR: return 64;
634  case E_ITEM_SUGAR_CANE: return 64;
635  case E_ITEM_TIPPED_ARROW: return 64;
636  case E_ITEM_WHEAT: return 64;
637  case E_ITEM_WOODEN_DOOR: return 64;
638  // By default items don't stack:
639  default: return 1;
640  }
641 }
642 
643 
644 
645 
646 
648 {
649  // TODO: Rewrite this to list all tools specifically
650  return
651  ((m_ItemType >= 256) && (m_ItemType <= 259)) ||
652  (m_ItemType == 261) ||
653  ((m_ItemType >= 267) && (m_ItemType <= 279)) ||
654  ((m_ItemType >= 283) && (m_ItemType <= 286)) ||
655  ((m_ItemType >= 290) && (m_ItemType <= 294)) ||
656  (m_ItemType == 325) ||
657  (m_ItemType == 346);
658 }
659 
660 
661 
662 
663 
665 {
666  return false;
667 }
668 
669 
670 
671 
672 
673 bool cItemHandler::IsDrinkable(short a_ItemDamage)
674 {
675  UNUSED(a_ItemDamage);
676 
677  return false;
678 }
679 
680 
681 
682 
683 
685 {
686  // We can place any block that has a corresponding E_BLOCK_TYPE:
687  return (m_ItemType >= 1) && (m_ItemType <= E_BLOCK_MAX_TYPE_ID);
688 }
689 
690 
691 
692 
693 
695 {
696  UNUSED(a_ItemType);
697  return false;
698 }
699 
700 
701 
702 
703 
705 {
706  switch (a_BlockType)
707  {
708  case E_BLOCK_ANVIL:
709  case E_BLOCK_BONE_BLOCK:
710  case E_BLOCK_BRICK:
711  case E_BLOCK_CAULDRON:
712  case E_BLOCK_COAL_ORE:
713  case E_BLOCK_COBBLESTONE:
716  case E_BLOCK_COBWEB:
718  case E_BLOCK_DIAMOND_ORE:
721  case E_BLOCK_EMERALD_ORE:
723  case E_BLOCK_END_BRICKS:
724  case E_BLOCK_END_STONE:
725  case E_BLOCK_FURNACE:
726  case E_BLOCK_GOLD_BLOCK:
727  case E_BLOCK_GOLD_ORE:
728  case E_BLOCK_IRON_BLOCK:
729  case E_BLOCK_IRON_ORE:
731  case E_BLOCK_LAPIS_BLOCK:
732  case E_BLOCK_LAPIS_ORE:
733  case E_BLOCK_LIT_FURNACE:
734  case E_BLOCK_MAGMA:
735  case E_BLOCK_MOB_SPAWNER:
740  case E_BLOCK_NETHERRACK:
742  case E_BLOCK_OBSERVER:
743  case E_BLOCK_OBSIDIAN:
748  case E_BLOCK_PURPUR_SLAB:
756  case E_BLOCK_SANDSTONE:
757  case E_BLOCK_SNOW:
758  case E_BLOCK_STONE:
762  case E_BLOCK_STONE_SLAB:
763  case E_BLOCK_VINES:
764  {
765  return false;
766  }
767  default: return true;
768  }
769 }
770 
771 
772 
773 
774 
776  cWorld * a_World, cPlayer * a_Player,
777  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
778  int a_CursorX, int a_CursorY, int a_CursorZ,
779  BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
780 )
781 {
782  ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers
783 
784  if (m_ItemType >= 256)
785  {
786  LOGERROR("%s: Item %d is not eligible for direct block placement!", __FUNCTION__, m_ItemType);
787  return false;
788  }
789 
790  cBlockHandler * BlockH = BlockHandler(static_cast<BLOCKTYPE>(m_ItemType));
791  cChunkInterface ChunkInterface(a_World->GetChunkMap());
792  return BlockH->GetPlacementBlockTypeMeta(
793  ChunkInterface, *a_Player,
794  a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
795  a_CursorX, a_CursorY, a_CursorZ,
796  a_BlockType, a_BlockMeta
797  );
798 }
799 
800 
801 
802 
803 
804 bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
805 {
806  auto FoodInfo = GetFoodInfo(a_Item);
807  return a_Player->Feed(FoodInfo.FoodLevel, FoodInfo.Saturation);
808 }
809 
810 
811 
812 
813 
815 {
816  UNUSED(a_Item);
817  return FoodInfo(0, 0);
818 }
819 
820 
821 
822 
823 
825 {
826  return 1.0f;
827 }
static bool m_HandlerInitialized
Definition: ItemHandler.h:170
cItemHandler(int a_ItemType)
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType)
Returns whether this tool / item can harvest a specific block (e.g.
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cBlockPluginInterface &a_PluginInterface, const cItem &a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
Called when the player tries to use the item (right mouse button).
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed.
Definition: Inventory.cpp:207
static cItemHandler * CreateItemHandler(int m_ItemType)
virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block)
Returns the strength to break a specific block.
virtual char GetMaxStackSize(void)
Returns the maximum stack size for a given item.
Definition: Player.h:27
virtual bool CanRepairWithRawMaterial(short a_ItemType)
Can the anvil repair this item, when a_Item is the second input?
static cItemHandler * GetItemHandler(int a_ItemType)
Definition: ItemHandler.cpp:74
virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action)
Get the durability lost which the item will get, when a specified action was performed.
virtual bool GetBlocksToPlace(cWorld &a_World, cPlayer &a_Player, const cItem &a_EquippedItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, sSetBlockVector &a_BlocksToSet)
Called from OnPlayerPlace() to determine the blocks that the current placement operation should set...
virtual bool GetPlacementBlockTypeMeta(cChunkInterface &a_ChunkInterface, cPlayer &a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Called before a block is placed into a world.
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the specified block, and spawns the appropriate pickups for it.
Definition: World.cpp:2200
virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, const cItem &a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
Called while the player digs a block using this item.
void LOGERROR(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:183
virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item)
Called after the player has eaten this item.
static const int Height
Definition: ChunkDef.h:135
bool PlaceBlocks(const sSetBlockVector &a_Blocks)
Calls the block placement hooks and places the blocks in the world.
Definition: Player.cpp:2788
This interface is used to decouple block handlers from the cPluginManager dependency through cWorld...
void AddFaceDirection(int &a_BlockX, int &a_BlockY, int &a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse=false)
Definition: Defines.h:859
void SendEquippedSlot()
Sends the equipped item slot to the client.
Definition: Inventory.cpp:303
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Retrieves the block type and meta at the specified coords.
Definition: World.cpp:1909
Definition: World.h:65
virtual FoodInfo GetFoodInfo(const cItem *a_Item)
Returns the FoodInfo for this item.
static cItemHandler * m_ItemHandler[E_ITEM_LAST+1]
Definition: ItemHandler.h:169
static void Deinit()
virtual bool IsTool(void)
Indicates if this item is a tool.
virtual bool OnPlayerPlace(cWorld &a_World, cPlayer &a_Player, const cItem &a_EquippedItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
Called when the player tries to place the item (right mouse button, IsPlaceable() == true)...
bool Feed(int a_Food, double a_Saturation)
Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full".
Definition: Player.cpp:656
#define ASSERT(x)
Definition: Globals.h:335
virtual bool GetPlacementBlockTypeMeta(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Called when the player right-clicks with this item and IsPlaceable() == true, and OnPlayerPlace() is ...
#define UNUSED
Definition: Globals.h:152
cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockInfo.h:159
cChunkMap * GetChunkMap(void)
Definition: World.h:1044
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc...
Definition: Defines.h:29
virtual bool IsPlaceable(void)
Blocks simply get placed.
bool IsGameModeSurvival(void) const
Returns true if the player is in Survival mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1269
Maximum BlockType number used.
Definition: BlockID.h:277
virtual bool IsDrinkable(short a_ItemDamage)
Indicates if this item is drinkable.
void UseEquippedItem(short a_Damage=1)
Damage the player&#39;s equipped item by a_Damage, possibly less if the equipped item is enchanted...
Definition: Player.cpp:2397
Definition: Entity.h:73
virtual void OnEntityAttack(cPlayer *a_Attacker, cEntity *a_AttackedEntity)
Called when a player attacks a other entity.
cInventory & GetInventory(void)
Definition: Player.h:136
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:290
eDurabilityLostAction
Actions that may cause durability of an item may be lost, where the magnitude of the loss depends on ...
Definition: ItemHandler.h:27
Definition: Item.h:36
virtual bool IsFood(void)
Indicates if this item is food.
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:564
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer &a_Player) override
Sends the block on those coords to the player.
Definition: World.cpp:2224
virtual bool EatItem(cPlayer *a_Player, cItem *a_Item)
Lets the player eat a selected item.