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 "AnvilMenu.h"
8
9AnvilMenu::AnvilMenu(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, true, 2) );
13 cost = 0;
14 repairItemCountCost = 0;
15
16 this->level = level;
17 x = xt;
18 y = yt;
19 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 AnvilMenu::slotsChanged(shared_ptr<Container> container)
42{
43 AbstractContainerMenu::slotsChanged();
44
45 if (container == repairSlots) createResult();
46}
47
48void AnvilMenu::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 || input->id == EnchantedBookItem::enchantedBook_Id) 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.empty())
199 {
200 if (input->hasCustomHoverName())
201 {
202 namingCost = input->isDamageableItem() ? 7 : input->count * 5;
203
204 price += namingCost;
205 if (DEBUG_COST)
206 {
207 app.DebugPrintf("Un-naming cost; price is now %d (went up by %d)", price, namingCost);
208 }
209 result->resetHoverName();
210 }
211 }
212 else if (itemName.length() > 0 && !equalsIgnoreCase(itemName, input->getHoverName()) && itemName.length() > 0)
213 {
214 namingCost = input->isDamageableItem() ? 7 : input->count * 5;
215
216 price += namingCost;
217 if (DEBUG_COST)
218 {
219 app.DebugPrintf("Naming cost; price is now %d (went up by %d)", price, namingCost);
220 }
221
222 if (input->hasCustomHoverName())
223 {
224 tax += namingCost / 2;
225
226 if (DEBUG_COST)
227 {
228 app.DebugPrintf("Already-named tax; tax is now %d (went up by %d)", tax, (namingCost / 2));
229 }
230 }
231
232 result->setHoverName(itemName);
233 }
234
235 int count = 0;
236 for(AUTO_VAR(it, enchantments->begin()); it != enchantments->end(); ++it)
237 {
238 int id = it->first;
239 Enchantment *enchantment = Enchantment::enchantments[id];
240 int level = it->second;
241 int fee = 0;
242
243 count++;
244
245 switch (enchantment->getFrequency())
246 {
247 case Enchantment::FREQ_COMMON:
248 fee = 1;
249 break;
250 case Enchantment::FREQ_UNCOMMON:
251 fee = 2;
252 break;
253 case Enchantment::FREQ_RARE:
254 fee = 4;
255 break;
256 case Enchantment::FREQ_VERY_RARE:
257 fee = 8;
258 break;
259 }
260
261 if (usingBook) fee = max(1, fee / 2);
262
263 tax += count + level * fee;
264 if (DEBUG_COST)
265 {
266 app.DebugPrintf("Enchantment tax; tax is now %d (went up by %d)", tax, (count + level * fee));
267 }
268 }
269
270 if (usingBook) tax = max(1, tax / 2);
271
272 cost = tax + price;
273 if (price <= 0)
274 {
275 if (DEBUG_COST) app.DebugPrintf("No purchase, only tax; aborting");
276 result = nullptr;
277 }
278 if (namingCost == price && namingCost > 0 && cost >= 40)
279 {
280 if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
281 app.DebugPrintf("Naming an item only, cost too high; giving discount to cap cost to 39 levels");
282 cost = 39;
283 }
284 if (cost >= 40 && !player->abilities.instabuild)
285 {
286 if (DEBUG_COST) app.DebugPrintf("Cost is too high; aborting");
287 result = nullptr;
288 }
289
290 if (result != NULL)
291 {
292 int baseCost = result->getBaseRepairCost();
293 if (addition != NULL && baseCost < addition->getBaseRepairCost()) baseCost = addition->getBaseRepairCost();
294 if (result->hasCustomHoverName()) baseCost -= 9;
295 if (baseCost < 0) baseCost = 0;
296 baseCost += 2;
297
298 result->setRepairCost(baseCost);
299 EnchantmentHelper::setEnchantments(enchantments, result);
300 }
301
302 resultSlots->setItem(0, result);
303 }
304
305 broadcastChanges();
306
307 if (DEBUG_COST)
308 {
309 if (level->isClientSide)
310 {
311 app.DebugPrintf("CLIENT Cost is %d (%d price, %d tax)\n", cost, price, tax);
312 }
313 else
314 {
315 app.DebugPrintf("SERVER Cost is %d (%d price, %d tax)\n", cost, price, tax);
316 }
317 }
318}
319
320void AnvilMenu::sendData(int id, int value)
321{
322 AbstractContainerMenu::sendData(id, value);
323}
324
325void AnvilMenu::addSlotListener(ContainerListener *listener)
326{
327 AbstractContainerMenu::addSlotListener(listener);
328 listener->setContainerData(this, DATA_TOTAL_COST, cost);
329}
330
331void AnvilMenu::setData(int id, int value)
332{
333 if (id == DATA_TOTAL_COST) cost = value;
334}
335
336void AnvilMenu::removed(shared_ptr<Player> player)
337{
338 AbstractContainerMenu::removed(player);
339 if (level->isClientSide) return;
340
341 for (int i = 0; i < repairSlots->getContainerSize(); i++)
342 {
343 shared_ptr<ItemInstance> item = repairSlots->removeItemNoUpdate(i);
344 if (item != NULL)
345 {
346 player->drop(item);
347 }
348 }
349}
350
351bool AnvilMenu::stillValid(shared_ptr<Player> player)
352{
353 if (level->getTile(x, y, z) != Tile::anvil_Id) return false;
354 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
355 return true;
356}
357
358shared_ptr<ItemInstance> AnvilMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex)
359{
360 shared_ptr<ItemInstance> clicked = nullptr;
361 Slot *slot = slots.at(slotIndex);
362 if (slot != NULL && slot->hasItem())
363 {
364 shared_ptr<ItemInstance> stack = slot->getItem();
365 clicked = stack->copy();
366
367 if (slotIndex == RESULT_SLOT)
368 {
369 if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, true))
370 {
371 return nullptr;
372 }
373 slot->onQuickCraft(stack, clicked);
374 }
375 else if (slotIndex == INPUT_SLOT || slotIndex == ADDITIONAL_SLOT)
376 {
377 if (!moveItemStackTo(stack, INV_SLOT_START, USE_ROW_SLOT_END, false))
378 {
379 return nullptr;
380 }
381 }
382 else if (slotIndex >= INV_SLOT_START && slotIndex < USE_ROW_SLOT_END)
383 {
384 if (!moveItemStackTo(stack, INPUT_SLOT, RESULT_SLOT, false))
385 {
386 return nullptr;
387 }
388 }
389 if (stack->count == 0)
390 {
391 slot->set(nullptr);
392 }
393 else
394 {
395 slot->setChanged();
396 }
397 if (stack->count == clicked->count)
398 {
399 return nullptr;
400 }
401 else
402 {
403 slot->onTake(player, stack);
404 }
405 }
406 return clicked;
407}
408
409void AnvilMenu::setItemName(const wstring &name)
410{
411 itemName = name;
412 if (getSlot(RESULT_SLOT)->hasItem())
413 {
414 shared_ptr<ItemInstance> item = getSlot(RESULT_SLOT)->getItem();
415
416 if (name.empty())
417 {
418 item->resetHoverName();
419 }
420 else
421 {
422 item->setHoverName(itemName);
423 }
424 }
425 createResult();
426}