CraftingStorage.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include <InMemoryBuffer.h>
  2. #include "CraftingStorage.h"
  3. #include "Game.h"
  4. #include "Inventory.h"
  5. #include "Item.h"
  6. BasicShapedCrafter::BasicShapedCrafter(int width, int height, Inventory* zInventory, Framework::Text recipieList)
  7. : zInventory(zInventory),
  8. currentRecipie(0),
  9. recipieList(recipieList),
  10. width(width),
  11. height(height)
  12. {
  13. for (int i = 0; i < width * height; i++)
  14. {
  15. ItemSlot* slot = new ItemSlot("CraftingGrid", 1, std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), INSIDE, INSIDE, 0);
  16. zInventory->addSlot(slot);
  17. craftingInput.add(slot);
  18. }
  19. std::function<void(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)> onChange = [this, recipieList](ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
  20. {
  21. if (!zSlot->getName().istGleich("CraftingGrid"))
  22. return;
  23. calculateOutputPreview();
  24. };
  25. zInventory->registerAfterPullStackCall(onChange);
  26. zInventory->registerAfterPushStackCall(onChange);
  27. zInventory->registerObserverAddedCall([this](Entity* zSource, Framework::Text id)
  28. {
  29. ShapedRecipie* old = currentRecipie;
  30. calculateOutputPreview();
  31. if (old == currentRecipie)
  32. {
  33. NetworkMessage* message = new NetworkMessage();
  34. getOutputPreview(message);
  35. message->addressGui(id);
  36. Game::INSTANCE->sendMessage(message, zSource);
  37. }
  38. });
  39. }
  40. void BasicShapedCrafter::getOutputPreview(NetworkMessage* zMessage)
  41. {
  42. if (currentRecipie)
  43. {
  44. Framework::Array<ItemInfo> output = currentRecipie->getOutput(this);
  45. Framework::InMemoryBuffer buffer;
  46. int count = 0;
  47. for (ItemInfo slot : output)
  48. {
  49. count++;
  50. int itemCount = slot.count;
  51. buffer.schreibe((char*)&itemCount, 4);
  52. if (itemCount > 0)
  53. {
  54. float f = slot.hp;
  55. buffer.schreibe((char*)&f, 4);
  56. f = slot.maxHp;
  57. buffer.schreibe((char*)&f, 4);
  58. f = slot.durability;
  59. buffer.schreibe((char*)&f, 4);
  60. f = slot.maxDurability;
  61. buffer.schreibe((char*)&f, 4);
  62. int id = slot.type;
  63. buffer.schreibe((char*)&id, 4);
  64. }
  65. }
  66. char* msg = new char[5 + buffer.getSize()];
  67. msg[0] = 100; // set crafting result
  68. *(int*)(msg + 1) = count;
  69. buffer.lese(msg + 5, (int)buffer.getSize());
  70. zMessage->setMessage(msg, 5 + (int)buffer.getSize());
  71. }
  72. else
  73. {
  74. char* msg = new char[5];
  75. msg[0] = 100; // set crafting result
  76. *(int*)(msg + 1) = 0;
  77. zMessage->setMessage(msg, 5);
  78. }
  79. }
  80. bool BasicShapedCrafter::isAllAvailable(Framework::RCArray<ItemFilter>& filters, int width, int height)
  81. {
  82. for (int x = 0; x <= this->width - width; x++)
  83. {
  84. for (int y = 0; y <= this->height - height; y++)
  85. {
  86. bool wrong = 0;
  87. for (int w = 0; w < width; w++)
  88. {
  89. for (int h = 0; h < height; h++)
  90. {
  91. ItemFilter* f = filters.z(h * width + w);
  92. ItemSlot* s = craftingInput.get((h + y) * this->width + (x + w));
  93. const Item* item = 0;
  94. if (s && s->zStack())
  95. item = s->zStack()->zItem();
  96. wrong |= (item && !f) || (!item && f);
  97. wrong |= item && f && !f->matchItem(item);
  98. if (wrong)
  99. break;
  100. }
  101. if (wrong)
  102. break;
  103. }
  104. if (!wrong)
  105. {
  106. int i = 0;
  107. for (ItemSlot* slot : craftingInput)
  108. {
  109. int w = i % this->width;
  110. int h = i / this->width;
  111. if ((w < x || w >= x + width || h < y || h >= y + height) && slot->zStack())
  112. return 0; // more items then needed are in crafting grid
  113. i++;
  114. }
  115. return 1;
  116. }
  117. }
  118. }
  119. return 0;
  120. }
  121. bool BasicShapedCrafter::hasFreeSpace(const Item* zItem, int amount)
  122. {
  123. ItemStack* stack = new ItemStack(zItem->zItemType()->cloneItem(zItem), amount);
  124. int addable = zInventory->numberOfAddableItems(stack, NO_DIRECTION);
  125. stack->release();
  126. return addable >= amount;
  127. }
  128. bool BasicShapedCrafter::consume(Framework::RCArray<ItemFilter>& filters, Framework::RCArray<ItemModifier>& modfiers, int width, int height)
  129. {
  130. int beginX = this->width;
  131. int beginY = this->height;
  132. SourceSlotBlacklistFilter otherSlots;
  133. for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
  134. {
  135. if (!craftingInput.get(i)->isEmpty())
  136. {
  137. int x = i % this->width;
  138. int y = i / this->width;
  139. beginX = MIN(beginX, x);
  140. beginY = MIN(beginY, y);
  141. }
  142. otherSlots.addBlackListSlotId(craftingInput.get(i)->getId());
  143. }
  144. for (int x = 0; x < width; x++)
  145. {
  146. for (int y = 0; y < height; y++)
  147. {
  148. ItemSlot* target = craftingInput.get((y + beginY) * this->width + x + beginX);
  149. ItemStack* stack = zInventory->takeItemsOut(target, 1, INSIDE);
  150. if (stack)
  151. {
  152. if (stack->getSize() > 0 && stack->zItem())
  153. {
  154. ItemModifier* m = modfiers.z(y * width + x);
  155. if (m)
  156. m->applyOn((Item*)stack->zItem());
  157. }
  158. if (stack->zItem()->getHp() == 0)
  159. stack->release();
  160. else if (stack->zItem()->getDurability() == 0)
  161. {
  162. Item* broken = stack->zItem()->zItemType()->breakItem(stack->zItem());
  163. stack->release();
  164. if (broken)
  165. {
  166. ItemStack* brokenStack = new ItemStack(broken, 1);
  167. zInventory->addItems(brokenStack, INSIDE);
  168. // TODO: if brokenStack is not empty spawn an item entity
  169. brokenStack->release();
  170. }
  171. }
  172. else
  173. {
  174. // TODO: transfer all items from target to other slots or drop them
  175. zInventory->addItems(target, stack, INSIDE);
  176. // TODO: if stack is not empty spawn an item entity
  177. }
  178. }
  179. ItemFilter* f = filters.z(y * width + x);
  180. if (f)
  181. {
  182. if (target->isEmpty())
  183. {
  184. Framework::Array< ItemSlot*> tmp;
  185. tmp.add(target);
  186. CombinedItemFilter combinedFilter(dynamic_cast<ItemFilter*>(f->getThis()), dynamic_cast<ItemFilter*>(otherSlots.getThis()), [](bool a, bool b)
  187. {
  188. return a && b;
  189. });
  190. zInventory->localTransaction(0, &tmp, &combinedFilter, 1, NO_DIRECTION, INSIDE);
  191. }
  192. }
  193. }
  194. }
  195. return 1;
  196. }
  197. void BasicShapedCrafter::addCraftingResult(ItemStack* stack)
  198. {
  199. zInventory->addItems(stack, NO_DIRECTION);
  200. }
  201. void BasicShapedCrafter::applyCurrentRecipie()
  202. {
  203. if (currentRecipie && currentRecipie->testApplicability(this))
  204. currentRecipie->apply(this);
  205. }
  206. void BasicShapedCrafter::calculateOutputPreview()
  207. {
  208. ShapedRecipieList* recipies = Game::INSTANCE->getRecipies().zShapedRecipieList(recipieList);
  209. if (recipies)
  210. {
  211. ShapedRecipie* recipie = recipies->zFirstRecipie(this);
  212. if (recipie != currentRecipie)
  213. {
  214. currentRecipie = recipie;
  215. NetworkMessage* message = new NetworkMessage();
  216. getOutputPreview(message);
  217. zInventory->notyObservers(message);
  218. }
  219. }
  220. }