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