the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 771 lines 20 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.player.h" 3#include "net.minecraft.world.item.h" 4#include "net.minecraft.world.level.redstone.h" 5#include "Slot.h" 6#include "AbstractContainerMenu.h" 7 8// 4J Stu - The java does not have ctor here (being an abstract) but we need one to initialise the member variables 9// TODO Make sure all derived classes also call this 10AbstractContainerMenu::AbstractContainerMenu() 11{ 12 containerId = 0; 13 14 changeUid = 0; 15 16 quickcraftType = -1; 17 quickcraftStatus = 0; 18 19 m_bNeedsRendered = false; 20} 21 22AbstractContainerMenu::~AbstractContainerMenu() 23{ 24 for( unsigned int i = 0; i < slots.size(); i++ ) 25 { 26 delete slots.at(i); 27 } 28} 29 30Slot *AbstractContainerMenu::addSlot(Slot *slot) 31{ 32 slot->index = (int)slots.size(); 33 slots.push_back(slot); 34 lastSlots.push_back(nullptr); 35 return slot; 36} 37 38 39void AbstractContainerMenu::addSlotListener(ContainerListener *listener) 40{ 41 containerListeners.push_back(listener); 42 43 vector<shared_ptr<ItemInstance> > *items = getItems(); 44 listener->refreshContainer(this, items); 45 delete items; 46 broadcastChanges(); 47} 48 49void AbstractContainerMenu::removeSlotListener(ContainerListener *listener) 50{ 51 AUTO_VAR(it, std::find(containerListeners.begin(), containerListeners.end(), listener) ); 52 if(it != containerListeners.end()) containerListeners.erase(it); 53} 54 55vector<shared_ptr<ItemInstance> > *AbstractContainerMenu::getItems() 56{ 57 vector<shared_ptr<ItemInstance> > *items = new vector<shared_ptr<ItemInstance> >(); 58 AUTO_VAR(itEnd, slots.end()); 59 for (AUTO_VAR(it, slots.begin()); it != itEnd; it++) 60 { 61 items->push_back((*it)->getItem()); 62 } 63 return items; 64} 65 66void AbstractContainerMenu::sendData(int id, int value) 67{ 68 AUTO_VAR(itEnd, containerListeners.end()); 69 for (AUTO_VAR(it, containerListeners.begin()); it != itEnd; it++) 70 { 71 (*it)->setContainerData(this, id, value); 72 } 73} 74 75void AbstractContainerMenu::broadcastChanges() 76{ 77 for (unsigned int i = 0; i < slots.size(); i++) 78 { 79 shared_ptr<ItemInstance> current = slots.at(i)->getItem(); 80 shared_ptr<ItemInstance> expected = lastSlots.at(i); 81 if (!ItemInstance::matches(expected, current)) 82 { 83 // 4J Stu - Added 0 count check. There is a bug in the Java with anvils that means this broadcast 84 // happens while we are in the middle of quickmoving, and before the slot properly gets set to null 85 expected = (current == NULL || current->count == 0) ? nullptr : current->copy(); 86 lastSlots[i] = expected; 87 m_bNeedsRendered = true; 88 89 AUTO_VAR(itEnd, containerListeners.end()); 90 for (AUTO_VAR(it, containerListeners.begin()); it != itEnd; it++) 91 { 92 (*it)->slotChanged(this, i, expected); 93 } 94 } 95 } 96} 97 98bool AbstractContainerMenu::needsRendered() 99{ 100 bool needsRendered = m_bNeedsRendered; 101 m_bNeedsRendered = false; 102 103 for (unsigned int i = 0; i < slots.size(); i++) 104 { 105 shared_ptr<ItemInstance> current = slots.at(i)->getItem(); 106 shared_ptr<ItemInstance> expected = lastSlots.at(i); 107 if (!ItemInstance::matches(expected, current)) 108 { 109 expected = current == NULL ? nullptr : current->copy(); 110 lastSlots[i] = expected; 111 needsRendered = true; 112 } 113 } 114 115 return needsRendered; 116} 117 118bool AbstractContainerMenu::clickMenuButton(shared_ptr<Player> player, int buttonId) 119{ 120 return false; 121} 122 123Slot *AbstractContainerMenu::getSlotFor(shared_ptr<Container> c, int index) 124{ 125 AUTO_VAR(itEnd, slots.end()); 126 for (AUTO_VAR(it, slots.begin()); it != itEnd; it++) 127 { 128 Slot *slot = *it; //slots->at(i); 129 if (slot->isAt(c, index)) 130 { 131 return slot; 132 } 133 } 134 return NULL; 135} 136 137Slot *AbstractContainerMenu::getSlot(int index) 138{ 139 return slots.at(index); 140} 141 142shared_ptr<ItemInstance> AbstractContainerMenu::quickMoveStack(shared_ptr<Player> player, int slotIndex) 143{ 144 Slot *slot = slots.at(slotIndex); 145 if (slot != NULL) 146 { 147 return slot->getItem(); 148 } 149 return nullptr; 150} 151 152shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int buttonNum, int clickType, shared_ptr<Player> player, bool looped) // 4J Added looped param 153{ 154 shared_ptr<ItemInstance> clickedEntity = nullptr; 155 shared_ptr<Inventory> inventory = player->inventory; 156 157 if (clickType == CLICK_QUICK_CRAFT) 158 { 159 int expectedStatus = quickcraftStatus; 160 quickcraftStatus = getQuickcraftHeader(buttonNum); 161 162 if ((expectedStatus != QUICKCRAFT_HEADER_CONTINUE || quickcraftStatus != QUICKCRAFT_HEADER_END) && expectedStatus != quickcraftStatus) 163 { 164 resetQuickCraft(); 165 } 166 else if (inventory->getCarried() == NULL) 167 { 168 resetQuickCraft(); 169 } 170 else if (quickcraftStatus == QUICKCRAFT_HEADER_START) 171 { 172 quickcraftType = getQuickcraftType(buttonNum); 173 174 if (isValidQuickcraftType(quickcraftType)) 175 { 176 quickcraftStatus = QUICKCRAFT_HEADER_CONTINUE; 177 quickcraftSlots.clear(); 178 } 179 else 180 { 181 resetQuickCraft(); 182 } 183 } 184 else if (quickcraftStatus == QUICKCRAFT_HEADER_CONTINUE) 185 { 186 Slot *slot = slots.at(slotIndex); 187 188 if (slot != NULL && canItemQuickReplace(slot, inventory->getCarried(), true) && slot->mayPlace(inventory->getCarried()) && inventory->getCarried()->count > quickcraftSlots.size() && canDragTo(slot)) 189 { 190 quickcraftSlots.insert(slot); 191 } 192 } 193 else if (quickcraftStatus == QUICKCRAFT_HEADER_END) 194 { 195 if (!quickcraftSlots.empty()) 196 { 197 shared_ptr<ItemInstance> source = inventory->getCarried()->copy(); 198 int remaining = inventory->getCarried()->count; 199 200 for(AUTO_VAR(it, quickcraftSlots.begin()); it != quickcraftSlots.end(); ++it) 201 { 202 Slot *slot = *it; 203 if (slot != NULL && canItemQuickReplace(slot, inventory->getCarried(), true) && slot->mayPlace(inventory->getCarried()) && inventory->getCarried()->count >= quickcraftSlots.size() && canDragTo(slot)) 204 { 205 shared_ptr<ItemInstance> copy = source->copy(); 206 int carry = slot->hasItem() ? slot->getItem()->count : 0; 207 getQuickCraftSlotCount(&quickcraftSlots, quickcraftType, copy, carry); 208 209 if (copy->count > copy->getMaxStackSize()) copy->count = copy->getMaxStackSize(); 210 if (copy->count > slot->getMaxStackSize()) copy->count = slot->getMaxStackSize(); 211 212 remaining -= copy->count - carry; 213 slot->set(copy); 214 } 215 } 216 217 source->count = remaining; 218 if (source->count <= 0) 219 { 220 source = nullptr; 221 } 222 inventory->setCarried(source); 223 } 224 225 resetQuickCraft(); 226 } 227 else 228 { 229 resetQuickCraft(); 230 } 231 } 232 else if (quickcraftStatus != QUICKCRAFT_HEADER_START) 233 { 234 resetQuickCraft(); 235 } 236 else if ((clickType == CLICK_PICKUP || clickType == CLICK_QUICK_MOVE) && (buttonNum == 0 || buttonNum == 1)) 237 { 238 if (slotIndex == SLOT_CLICKED_OUTSIDE) 239 { 240 if (inventory->getCarried() != NULL) 241 { 242 if (slotIndex == SLOT_CLICKED_OUTSIDE) 243 { 244 if (buttonNum == 0) 245 { 246 player->drop(inventory->getCarried()); 247 inventory->setCarried(nullptr); 248 } 249 if (buttonNum == 1) 250 { 251 player->drop(inventory->getCarried()->remove(1)); 252 if (inventory->getCarried()->count == 0) inventory->setCarried(nullptr); 253 } 254 255 } 256 } 257 } 258 else if (clickType == CLICK_QUICK_MOVE) 259 { 260 if (slotIndex < 0) return nullptr; 261 Slot *slot = slots.at(slotIndex); 262 if(slot != NULL && slot->mayPickup(player)) 263 { 264 shared_ptr<ItemInstance> piiClicked = quickMoveStack(player, slotIndex); 265 if (piiClicked != NULL) 266 { 267 int oldType = piiClicked->id; 268 269 // 4J Stu - We ignore the return value for loopClicks, so don't make a copy 270 if(!looped) 271 { 272 clickedEntity = piiClicked->copy(); 273 } 274 275 // 4J Stu - Remove the reference to this before we start a recursive loop 276 piiClicked = nullptr; 277 278 if (slot != NULL) 279 { 280 if (slot->getItem() != NULL && slot->getItem()->id == oldType) 281 { 282 if(looped) 283 { 284 // Return a non-null value to indicate that we want to loop more 285 clickedEntity = shared_ptr<ItemInstance>(new ItemInstance(0,1,0)); 286 } 287 else 288 { 289 // 4J Stu - Brought forward loopClick from 1.2 to fix infinite recursion bug in creative 290 loopClick(slotIndex, buttonNum, true, player); 291 } 292 } 293 } 294 } 295 } 296 } 297 else 298 { 299 if (slotIndex < 0) return nullptr; 300 301 Slot *slot = slots.at(slotIndex); 302 if (slot != NULL) 303 { 304 shared_ptr<ItemInstance> clicked = slot->getItem(); 305 shared_ptr<ItemInstance> carried = inventory->getCarried(); 306 307 if (clicked != NULL) 308 { 309 clickedEntity = clicked->copy(); 310 } 311 312 if (clicked == NULL) 313 { 314 if (carried != NULL && slot->mayPlace(carried)) 315 { 316 int c = buttonNum == 0 ? carried->count : 1; 317 if (c > slot->getMaxStackSize()) 318 { 319 c = slot->getMaxStackSize(); 320 } 321 if (carried->count >= c) 322 { 323 slot->set(carried->remove(c)); 324 } 325 if (carried->count == 0) 326 { 327 inventory->setCarried(nullptr); 328 } 329 } 330 } 331 // 4J Added for dyable armour and combinining damaged items 332 else if (buttonNum == 1 && mayCombine(slot, carried)) 333 { 334 shared_ptr<ItemInstance> combined = slot->combine(carried); 335 if(combined != NULL) 336 { 337 slot->set(combined); 338 if(!player->abilities.instabuild) carried->remove(1); 339 if (carried->count == 0) 340 { 341 inventory->setCarried(nullptr); 342 } 343 } 344 } 345 else if (slot->mayPickup(player)) 346 { 347 if (carried == NULL) 348 { 349 // pick up to empty hand 350 int c = buttonNum == 0 ? clicked->count : (clicked->count + 1) / 2; 351 shared_ptr<ItemInstance> removed = slot->remove(c); 352 353 inventory->setCarried(removed); 354 if (clicked->count == 0) 355 { 356 slot->set(nullptr); 357 } 358 slot->onTake(player, inventory->getCarried()); 359 } 360 else if (slot->mayPlace(carried)) 361 { 362 // put down and/or pick up 363 if (clicked->id != carried->id || clicked->getAuxValue() != carried->getAuxValue() || !ItemInstance::tagMatches(clicked, carried)) 364 { 365 // no match, replace 366 if (carried->count <= slot->getMaxStackSize()) 367 { 368 slot->set(carried); 369 inventory->setCarried(clicked); 370 } 371 } 372 else 373 { 374 // match, attempt to fill slot 375 int c = buttonNum == 0 ? carried->count : 1; 376 if (c > slot->getMaxStackSize() - clicked->count) 377 { 378 c = slot->getMaxStackSize() - clicked->count; 379 } 380 if (c > carried->getMaxStackSize() - clicked->count) 381 { 382 c = carried->getMaxStackSize() - clicked->count; 383 } 384 carried->remove(c); 385 if (carried->count == 0) 386 { 387 inventory->setCarried(nullptr); 388 } 389 clicked->count += c; 390 } 391 } 392 else 393 { 394 // pick up to non-empty hand 395 if (clicked->id == carried->id && carried->getMaxStackSize() > 1 && (!clicked->isStackedByData() || clicked->getAuxValue() == carried->getAuxValue()) 396 && ItemInstance::tagMatches(clicked, carried)) 397 { 398 int c = clicked->count; 399 if (c > 0 && c + carried->count <= carried->getMaxStackSize()) 400 { 401 carried->count += c; 402 clicked = slot->remove(c); 403 if (clicked->count == 0) slot->set(nullptr); 404 slot->onTake(player, inventory->getCarried()); 405 } 406 } 407 } 408 409 410 } 411 slot->setChanged(); 412 } 413 } 414 } 415 else if (clickType == CLICK_SWAP && buttonNum >= 0 && buttonNum < 9) 416 { 417 Slot *slot = slots.at(slotIndex); 418 if (slot->mayPickup(player)) 419 { 420 shared_ptr<ItemInstance> current = inventory->getItem(buttonNum); 421 bool canMove = current == NULL || (slot->container == inventory && slot->mayPlace(current)); 422 int freeSlot = -1; 423 424 if (!canMove) 425 { 426 freeSlot = inventory->getFreeSlot(); 427 canMove |= freeSlot > -1; 428 } 429 430 if (slot->hasItem() && canMove) 431 { 432 shared_ptr<ItemInstance> taking = slot->getItem(); 433 inventory->setItem(buttonNum, taking); 434 435 if ((slot->container == inventory && slot->mayPlace(current)) || current == NULL) 436 { 437 slot->remove(taking->count); 438 slot->set(current); 439 slot->onTake(player, taking); 440 } 441 else if (freeSlot > -1) 442 { 443 inventory->add(current); 444 slot->remove(taking->count); 445 slot->set(nullptr); 446 slot->onTake(player, taking); 447 } 448 } 449 else if (!slot->hasItem() && current != NULL && slot->mayPlace(current)) 450 { 451 inventory->setItem(buttonNum, nullptr); 452 slot->set(current); 453 } 454 } 455 } 456 else if (clickType == CLICK_CLONE && player->abilities.instabuild && inventory->getCarried() == NULL && slotIndex >= 0) 457 { 458 Slot *slot = slots.at(slotIndex); 459 if (slot != NULL && slot->hasItem()) 460 { 461 shared_ptr<ItemInstance> copy = slot->getItem()->copy(); 462 copy->count = copy->getMaxStackSize(); 463 inventory->setCarried(copy); 464 } 465 } 466 else if (clickType == CLICK_THROW && inventory->getCarried() == NULL && slotIndex >= 0) 467 { 468 Slot *slot = slots.at(slotIndex); 469 if (slot != NULL && slot->hasItem() && slot->mayPickup(player)) 470 { 471 shared_ptr<ItemInstance> item = slot->remove(buttonNum == 0 ? 1 : slot->getItem()->count); 472 slot->onTake(player, item); 473 player->drop(item); 474 } 475 } 476 else if (clickType == CLICK_PICKUP_ALL && slotIndex >= 0) 477 { 478 Slot *slot = slots.at(slotIndex); 479 shared_ptr<ItemInstance> carried = inventory->getCarried(); 480 481 if (carried != NULL && (slot == NULL || !slot->hasItem() || !slot->mayPickup(player))) 482 { 483 int start = buttonNum == 0 ? 0 : slots.size() - 1; 484 int step = buttonNum == 0 ? 1 : -1; 485 486 for (int pass = 0; pass < 2; pass++ ) 487 { 488 // In the first pass, we only get partial stacks. 489 for (int i = start; i >= 0 && i < slots.size() && carried->count < carried->getMaxStackSize(); i += step) 490 { 491 Slot *target = slots.at(i); 492 493 if (target->hasItem() && canItemQuickReplace(target, carried, true) && target->mayPickup(player) && canTakeItemForPickAll(carried, target)) 494 { 495 if (pass == 0 && target->getItem()->count == target->getItem()->getMaxStackSize()) continue; 496 int count = min(carried->getMaxStackSize() - carried->count, target->getItem()->count); 497 shared_ptr<ItemInstance> removed = target->remove(count); 498 carried->count += count; 499 500 if (removed->count <= 0) 501 { 502 target->set(nullptr); 503 } 504 target->onTake(player, removed); 505 } 506 } 507 } 508 } 509 510 broadcastChanges(); 511 } 512 return clickedEntity; 513} 514 515bool AbstractContainerMenu::canTakeItemForPickAll(shared_ptr<ItemInstance> carried, Slot *target) 516{ 517 return true; 518} 519 520// 4J Stu - Brought forward from 1.2 to fix infinite recursion bug in creative 521void AbstractContainerMenu::loopClick(int slotIndex, int buttonNum, bool quickKeyHeld, shared_ptr<Player> player) 522{ 523 while( clicked(slotIndex, buttonNum, CLICK_QUICK_MOVE, player, true) != NULL) 524 { 525 } 526} 527 528bool AbstractContainerMenu::mayCombine(Slot *slot, shared_ptr<ItemInstance> item) 529{ 530 return false; 531} 532 533void AbstractContainerMenu::removed(shared_ptr<Player> player) 534{ 535 shared_ptr<Inventory> inventory = player->inventory; 536 if (inventory->getCarried() != NULL) 537 { 538 player->drop(inventory->getCarried()); 539 inventory->setCarried(nullptr); 540 } 541} 542 543void AbstractContainerMenu::slotsChanged()// 4J used to take a shared_ptr<Container> but wasn't using it, so removed to simplify things 544{ 545 broadcastChanges(); 546} 547 548bool AbstractContainerMenu::isPauseScreen() 549{ 550 return false; 551} 552 553void AbstractContainerMenu::setItem(unsigned int slot, shared_ptr<ItemInstance> item) 554{ 555 getSlot(slot)->set(item); 556} 557 558void AbstractContainerMenu::setAll(ItemInstanceArray *items) 559{ 560 for (unsigned int i = 0; i < items->length; i++) 561 { 562 getSlot(i)->set( (*items)[i] ); 563 } 564} 565 566void AbstractContainerMenu::setData(int id, int value) 567{ 568} 569 570short AbstractContainerMenu::backup(shared_ptr<Inventory> inventory) 571{ 572 changeUid++; 573 return changeUid; 574} 575 576bool AbstractContainerMenu::isSynched(shared_ptr<Player> player) 577{ 578 return !(unSynchedPlayers.find(player) != unSynchedPlayers.end()); 579} 580 581void AbstractContainerMenu::setSynched(shared_ptr<Player> player, bool synched) 582{ 583 if (synched) 584 { 585 AUTO_VAR(it, unSynchedPlayers.find(player)); 586 587 if(it != unSynchedPlayers.end()) unSynchedPlayers.erase( it ); 588 } 589 else 590 { 591 unSynchedPlayers.insert(player); 592 } 593} 594 595// 4J Stu - Brought a few changes in this function forward from 1.2 to make it return a bool 596bool AbstractContainerMenu::moveItemStackTo(shared_ptr<ItemInstance> itemStack, int startSlot, int endSlot, bool backwards) 597{ 598 bool anythingChanged = false; 599 600 int destSlot = startSlot; 601 if (backwards) 602 { 603 destSlot = endSlot - 1; 604 } 605 606 // find stackable slots first 607 if (itemStack->isStackable()) 608 { 609 while (itemStack->count > 0 && ((!backwards && destSlot < endSlot) || (backwards && destSlot >= startSlot))) 610 { 611 612 Slot *slot = slots.at(destSlot); 613 shared_ptr<ItemInstance> target = slot->getItem(); 614 if (target != NULL && target->id == itemStack->id && (!itemStack->isStackedByData() || itemStack->getAuxValue() == target->getAuxValue()) 615 && ItemInstance::tagMatches(itemStack, target) ) 616 { 617 int totalStack = target->count + itemStack->count; 618 if (totalStack <= itemStack->getMaxStackSize()) 619 { 620 itemStack->count = 0; 621 target->count = totalStack; 622 slot->setChanged(); 623 anythingChanged = true; 624 } 625 else if (target->count < itemStack->getMaxStackSize()) 626 { 627 itemStack->count -= (itemStack->getMaxStackSize() - target->count); 628 target->count = itemStack->getMaxStackSize(); 629 slot->setChanged(); 630 anythingChanged = true; 631 } 632 } 633 634 if (backwards) 635 { 636 destSlot--; 637 } 638 else 639 { 640 destSlot++; 641 } 642 } 643 } 644 645 // find empty slot 646 if (itemStack->count > 0) 647 { 648 if (backwards) 649 { 650 destSlot = endSlot - 1; 651 } 652 else 653 { 654 destSlot = startSlot; 655 } 656 while ((!backwards && destSlot < endSlot) || (backwards && destSlot >= startSlot)) 657 { 658 Slot *slot = slots.at(destSlot); 659 shared_ptr<ItemInstance> target = slot->getItem(); 660 661 if (target == NULL) 662 { 663 slot->set(itemStack->copy()); 664 slot->setChanged(); 665 itemStack->count = 0; 666 anythingChanged = true; 667 break; 668 } 669 670 if (backwards) 671 { 672 destSlot--; 673 } 674 else 675 { 676 destSlot++; 677 } 678 } 679 } 680 return anythingChanged; 681} 682 683bool AbstractContainerMenu::isOverrideResultClick(int slotNum, int buttonNum) 684{ 685 return false; 686} 687 688int AbstractContainerMenu::getQuickcraftType(int mask) 689{ 690 return (mask >> 2) & 0x3; 691} 692 693int AbstractContainerMenu::getQuickcraftHeader(int mask) 694{ 695 return mask & 0x3; 696} 697 698int AbstractContainerMenu::getQuickcraftMask(int header, int type) 699{ 700 return (header & 0x3) | ((type & 0x3) << 2); 701} 702 703bool AbstractContainerMenu::isValidQuickcraftType(int type) 704{ 705 return type == QUICKCRAFT_TYPE_CHARITABLE || type == QUICKCRAFT_TYPE_GREEDY; 706} 707 708void AbstractContainerMenu::resetQuickCraft() 709{ 710 quickcraftStatus = QUICKCRAFT_HEADER_START; 711 quickcraftSlots.clear(); 712} 713 714bool AbstractContainerMenu::canItemQuickReplace(Slot *slot, shared_ptr<ItemInstance> item, bool ignoreSize) 715{ 716 bool canReplace = slot == NULL || !slot->hasItem(); 717 718 if (slot != NULL && slot->hasItem() && item != NULL && item->sameItem(slot->getItem()) && ItemInstance::tagMatches(slot->getItem(), item)) 719 { 720 canReplace |= slot->getItem()->count + (ignoreSize ? 0 : item->count) <= item->getMaxStackSize(); 721 } 722 723 return canReplace; 724} 725 726void AbstractContainerMenu::getQuickCraftSlotCount(unordered_set<Slot *> *quickCraftSlots, int quickCraftingType, shared_ptr<ItemInstance> item, int carry) 727{ 728 switch (quickCraftingType) 729 { 730 case QUICKCRAFT_TYPE_CHARITABLE: 731 item->count = Mth::floor(item->count / (float) quickCraftSlots->size()); 732 break; 733 case QUICKCRAFT_TYPE_GREEDY: 734 item->count = 1; 735 break; 736 } 737 738 item->count += carry; 739} 740 741bool AbstractContainerMenu::canDragTo(Slot *slot) 742{ 743 return true; 744} 745 746int AbstractContainerMenu::getRedstoneSignalFromContainer(shared_ptr<Container> container) 747{ 748 if (container == NULL) return 0; 749 int count = 0; 750 float totalPct = 0; 751 752 for (int i = 0; i < container->getContainerSize(); i++) 753 { 754 shared_ptr<ItemInstance> item = container->getItem(i); 755 756 if (item != NULL) 757 { 758 totalPct += item->count / (float) min(container->getMaxStackSize(), item->getMaxStackSize()); 759 count++; 760 } 761 } 762 763 totalPct /= container->getContainerSize(); 764 return Mth::floor(totalPct * (Redstone::SIGNAL_MAX - 1)) + (count > 0 ? 1 : 0); 765} 766 767// 4J Added 768bool AbstractContainerMenu::isValidIngredient(shared_ptr<ItemInstance> item, int slotId) 769{ 770 return true; 771}