CraftingStorage.cpp 8.1 KB

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