the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 426 lines 11 kB view raw
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}