the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "net.minecraft.world.inventory.h"
3#include "net.minecraft.world.entity.player.h"
4#include "net.minecraft.world.level.h"
5#include "net.minecraft.world.item.h"
6#include "net.minecraft.world.item.enchantment.h"
7#include "RepairMenu.h"
8
9RepairMenu::RepairMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt, shared_ptr<Player> player)
10{
11 resultSlots = shared_ptr<ResultContainer>( new ResultContainer() );
12 repairSlots = shared_ptr<RepairContainer>( new RepairContainer(this,IDS_REPAIR_AND_NAME, 2) );
13 cost = 0;
14 repairItemCountCost = 0;
15
16 this->level = level;
17 this->x = xt;
18 this->y = yt;
19 this->z = zt;
20 this->player = player;
21
22 addSlot(new Slot(repairSlots, INPUT_SLOT, 27, 43 + 4));
23 addSlot(new Slot(repairSlots, ADDITIONAL_SLOT, 76, 43 + 4));
24
25 // 4J Stu - Anonymous class here is now RepairResultSlot
26 addSlot(new RepairResultSlot(this, xt, yt, zt, resultSlots, RESULT_SLOT, 134, 43 + 4));
27
28 for (int y = 0; y < 3; y++)
29 {
30 for (int x = 0; x < 9; x++)
31 {
32 addSlot(new Slot(inventory, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
33 }
34 }
35 for (int x = 0; x < 9; x++)
36 {
37 addSlot(new Slot(inventory, x, 8 + x * 18, 142));
38 }
39}
40
41void RepairMenu::slotsChanged(shared_ptr<Container> container)
42{
43 AbstractContainerMenu::slotsChanged();
44
45 if (container == repairSlots) createResult();
46}
47
48void RepairMenu::createResult()
49{
50 shared_ptr<ItemInstance> input = repairSlots->getItem(INPUT_SLOT);
51 cost = 0;
52 int price = 0;
53 int tax = 0;
54 int namingCost = 0;
55
56 if (DEBUG_COST) app.DebugPrintf("----");
57
58 if (input == NULL)
59 {
60 resultSlots->setItem(0, nullptr);
61 cost = 0;
62 return;
63 }
64 else
65 {
66 shared_ptr<ItemInstance> result = input->copy();
67 shared_ptr<ItemInstance> addition = repairSlots->getItem(ADDITIONAL_SLOT);
68 unordered_map<int,int> *enchantments = EnchantmentHelper::getEnchantments(result);
69 bool usingBook = false;
70
71 tax += input->getBaseRepairCost() + (addition == NULL ? 0 : addition->getBaseRepairCost());
72 if (DEBUG_COST)
73 {
74 app.DebugPrintf("Starting with base repair tax of %d (%d + %d)\n", tax, input->getBaseRepairCost(), (addition == NULL ? 0 : addition->getBaseRepairCost()));
75 }
76
77 repairItemCountCost = 0;
78
79 if (addition != NULL)
80 {
81 usingBook = addition->id == Item::enchantedBook_Id && Item::enchantedBook->getEnchantments(addition)->size() > 0;
82
83 if (result->isDamageableItem() && Item::items[result->id]->isValidRepairItem(input, addition))
84 {
85 int repairAmount = min(result->getDamageValue(), result->getMaxDamage() / 4);
86 if (repairAmount <= 0)
87 {
88 resultSlots->setItem(0, nullptr);
89 cost = 0;
90 return;
91 }
92 else
93 {
94 int count = 0;
95 while (repairAmount > 0 && count < addition->count)
96 {
97 int resultDamage = result->getDamageValue() - repairAmount;
98 result->setAuxValue(resultDamage);
99 price += max(1, repairAmount / 100) + enchantments->size();
100
101 repairAmount = min(result->getDamageValue(), result->getMaxDamage() / 4);
102 count++;
103 }
104 repairItemCountCost = count;
105 }
106 }
107 else if (!usingBook && (result->id != addition->id || !result->isDamageableItem()))
108 {
109 resultSlots->setItem(0, nullptr);
110 cost = 0;
111 return;
112 }
113 else
114 {
115 if (result->isDamageableItem() && !usingBook)
116 {
117 int remaining1 = input->getMaxDamage() - input->getDamageValue();
118 int remaining2 = addition->getMaxDamage() - addition->getDamageValue();
119 int additional = remaining2 + result->getMaxDamage() * 12 / 100;
120 int remaining = remaining1 + additional;
121 int resultDamage = result->getMaxDamage() - remaining;
122 if (resultDamage < 0) resultDamage = 0;
123
124 if (resultDamage < result->getAuxValue())
125 {
126 result->setAuxValue(resultDamage);
127 price += max(1, additional / 100);
128 if (DEBUG_COST)
129 {
130 app.DebugPrintf("Repairing; price is now %d (went up by %d)\n", price, max(1, additional / 100) );
131 }
132 }
133 }
134
135 unordered_map<int, int> *additionalEnchantments = EnchantmentHelper::getEnchantments(addition);
136
137 for(AUTO_VAR(it, additionalEnchantments->begin()); it != additionalEnchantments->end(); ++it)
138 {
139 int id = it->first;
140 Enchantment *enchantment = Enchantment::enchantments[id];
141 AUTO_VAR(localIt, enchantments->find(id));
142 int current = localIt != enchantments->end() ? localIt->second : 0;
143 int level = it->second;
144 level = (current == level) ? level += 1 : max(level, current);
145 int extra = level - current;
146 bool compatible = enchantment->canEnchant(input);
147
148 if (player->abilities.instabuild) compatible = true;
149
150 for(AUTO_VAR(it2, enchantments->begin()); it2 != enchantments->end(); ++it2)
151 {
152 int other = it2->first;
153 if (other != id && !enchantment->isCompatibleWith(Enchantment::enchantments[other]))
154 {
155 compatible = false;
156
157 price += extra;
158 if (DEBUG_COST)
159 {
160 app.DebugPrintf("Enchantment incompatibility fee; price is now %d (went up by %d)\n", price, extra);
161 }
162 }
163 }
164
165 if (!compatible) continue;
166 if (level > enchantment->getMaxLevel()) level = enchantment->getMaxLevel();
167 (*enchantments)[id] = level;
168 int fee = 0;
169
170 switch (enchantment->getFrequency())
171 {
172 case Enchantment::FREQ_COMMON:
173 fee = 1;
174 break;
175 case Enchantment::FREQ_UNCOMMON:
176 fee = 2;
177 break;
178 case Enchantment::FREQ_RARE:
179 fee = 4;
180 break;
181 case Enchantment::FREQ_VERY_RARE:
182 fee = 8;
183 break;
184 }
185
186 if (usingBook) fee = max(1, fee / 2);
187
188 price += fee * extra;
189 if (DEBUG_COST)
190 {
191 app.DebugPrintf("Enchantment increase fee; price is now %d (went up by %d)\n", price, fee*extra);
192 }
193 }
194 delete additionalEnchantments;
195 }
196 }
197
198 if (itemName.length() > 0 && !equalsIgnoreCase(itemName, input->getHoverName()) && itemName.length() > 0)
199 {
200 namingCost = input->isDamageableItem() ? 7 : input->count * 5;
201
202 price += namingCost;
203 if (DEBUG_COST)
204 {
205 app.DebugPrintf("Naming cost; price is now %d (went up by %d)", price, namingCost);
206 }
207
208 if (input->hasCustomHoverName())
209 {
210 tax += namingCost / 2;
211
212 if (DEBUG_COST)
213 {
214 app.DebugPrintf("Already-named tax; tax is now %d (went up by %d)", tax, (namingCost / 2));
215 }
216 }
217
218 result->setHoverName(itemName);
219 }
220
221 int count = 0;
222 for(AUTO_VAR(it, enchantments->begin()); it != enchantments->end(); ++it)
223 {
224 int id = it->first;
225 Enchantment *enchantment = Enchantment::enchantments[id];
226 int level = it->second;
227 int fee = 0;
228
229 count++;
230
231 switch (enchantment->getFrequency())
232 {
233 case Enchantment::FREQ_COMMON:
234 fee = 1;
235 break;
236 case Enchantment::FREQ_UNCOMMON:
237 fee = 2;
238 break;
239 case Enchantment::FREQ_RARE:
240 fee = 4;
241 break;
242 case Enchantment::FREQ_VERY_RARE:
243 fee = 8;
244 break;
245 }
246
247 if (usingBook) fee = max(1, fee / 2);
248
249 tax += count + level * fee;
250 if (DEBUG_COST)
251 {
252 app.DebugPrintf("Enchantment tax; tax is now %d (went up by %d)", tax, (count + level * fee));
253 }
254 }
255
256 if (usingBook) tax = max(1, tax / 2);
257
258 cost = tax + price;
259 if (price <= 0)
260 {
261 if (DEBUG_COST) app.DebugPrintf("No purchase, only tax; aborting");
262 result = nullptr;
263 }
264 if (namingCost == price && namingCost > 0 && cost >= 40)
265 {
266 if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
267 app.DebugPrintf("Naming an item only, cost too high; giving discount to cap cost to 39 levels");
268 cost = 39;
269 }
270 if (cost >= 40 && !player->abilities.instabuild)
271 {
272 if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
273 result = nullptr;
274 }
275
276 if (result != NULL)
277 {
278 int baseCost = result->getBaseRepairCost();
279 if (addition != NULL && baseCost < addition->getBaseRepairCost()) baseCost = addition->getBaseRepairCost();
280 if (result->hasCustomHoverName()) baseCost -= 9;
281 if (baseCost < 0) baseCost = 0;
282 baseCost += 2;
283
284 result->setRepairCost(baseCost);
285 EnchantmentHelper::setEnchantments(enchantments, result);
286 }
287
288 resultSlots->setItem(0, result);
289 }
290
291 broadcastChanges();
292
293 if (DEBUG_COST)
294 {
295 if (level->isClientSide)
296 {
297 app.DebugPrintf("CLIENT Cost is %d (%d price, %d tax)\n", cost, price, tax);
298 }
299 else
300 {
301 app.DebugPrintf("SERVER Cost is %d (%d price, %d tax)\n", cost, price, tax);
302 }
303 }
304}
305
306void RepairMenu::sendData(int id, int value)
307{
308 AbstractContainerMenu::sendData(id, value);
309}
310
311void RepairMenu::addSlotListener(ContainerListener *listener)
312{
313 AbstractContainerMenu::addSlotListener(listener);
314 listener->setContainerData(this, DATA_TOTAL_COST, cost);
315}
316
317void RepairMenu::setData(int id, int value)
318{
319 if (id == DATA_TOTAL_COST) cost = value;
320}
321
322void RepairMenu::removed(shared_ptr<Player> player)
323{
324 AbstractContainerMenu::removed(player);
325 if (level->isClientSide) return;
326
327 for (int i = 0; i < repairSlots->getContainerSize(); i++)
328 {
329 shared_ptr<ItemInstance> item = repairSlots->removeItemNoUpdate(i);
330 if (item != NULL)
331 {
332 player->drop(item);
333 }
334 }
335}
336
337bool RepairMenu::stillValid(shared_ptr<Player> player)
338{
339 if (level->getTile(x, y, z) != Tile::anvil_Id) return false;
340 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
341 return true;
342}
343
344shared_ptr<ItemInstance> RepairMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex)
345{
346 shared_ptr<ItemInstance> clicked = nullptr;
347 Slot *slot = slots->at(slotIndex);
348 if (slot != NULL && slot->hasItem())
349 {
350 shared_ptr<ItemInstance> stack = slot->getItem();
351 clicked = stack->copy();
352
353 if (slotIndex == RESULT_SLOT)
354 {
355 if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, true))
356 {
357 return nullptr;
358 }
359 slot->onQuickCraft(stack, clicked);
360 }
361 else if (slotIndex == INPUT_SLOT || slotIndex == ADDITIONAL_SLOT)
362 {
363 if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, false))
364 {
365 return nullptr;
366 }
367 }
368 else if (slotIndex >= INV_SLOT_START && slotIndex < USE_ROW_SLOT_END)
369 {
370 if (!moveItemStackTo(stack, INPUT_SLOT, RESULT_SLOT, false))
371 {
372 return nullptr;
373 }
374 }
375 if (stack->count == 0)
376 {
377 slot->set(nullptr);
378 }
379 else
380 {
381 slot->setChanged();
382 }
383 if (stack->count == clicked->count)
384 {
385 return nullptr;
386 }
387 else
388 {
389 slot->onTake(player, stack);
390 }
391 }
392 return clicked;
393}
394
395void RepairMenu::setItemName(const wstring &name)
396{
397 this->itemName = name;
398 if (getSlot(RESULT_SLOT)->hasItem())
399 {
400 getSlot(RESULT_SLOT)->getItem()->setHoverName(itemName);
401 }
402 createResult();
403}