116 [$windowId, $slotId] =
ItemStackContainerIdTranslator::translate($info->getContainerName()->getContainerId(), $this->inventoryManager->getCurrentWindowId(), $info->getSlotId());
117 $windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
118 if($windowAndSlot ===
null){
119 throw new ItemStackRequestProcessException(
"No open inventory matches container UI ID: " . $info->getContainerName()->getContainerId() .
", slot ID: " . $info->getSlotId());
121 [$inventory, $slot] = $windowAndSlot;
123 throw new ItemStackRequestProcessException(
"No such inventory slot :" . $this->prettyInventoryAndSlot($inventory, $slot));
126 if($info->getStackId() !== $this->request->getRequestId()){
127 $this->matchItemStack($inventory, $slot, $info->getStackId());
130 return [$this->builder->getInventory($inventory), $slot];
149 return $this->takeCreatedItem($count);
151 $this->requestSlotInfos[] = $slotInfo;
152 [$inventory, $slot] = $this->getBuilderInventoryAndSlot($slotInfo);
158 $existingItem = $inventory->
getItem($slot);
159 if($existingItem->getCount() < $count){
160 throw new ItemStackRequestProcessException($this->prettyInventoryAndSlot($inventory, $slot) .
": Cannot take $count items from a stack of " . $existingItem->getCount());
163 $removed = $existingItem->pop($count);
164 $inventory->
setItem($slot, $existingItem);
203 if($item !== null && $item->isNull()){
206 if($this->nextCreatedItem !==
null){
209 if($this->createdItemFromCreativeInventory && $this->createdItemsTakenCount > 0){
210 $this->nextCreatedItem->setCount($this->createdItemsTakenCount);
212 }elseif($this->createdItemsTakenCount < $this->nextCreatedItem->getCount()){
213 throw new ItemStackRequestProcessException(
"Not all of the previous created item was taken");
216 $this->nextCreatedItem = $item;
217 $this->createdItemFromCreativeInventory = $creative;
218 $this->createdItemsTakenCount = 0;
225 if($this->specialTransaction !== null){
228 if($repetitions < 1){
231 if($repetitions > 256){
235 throw new ItemStackRequestProcessException(
"Cannot craft a recipe more than 256 times");
237 $craftingManager = $this->player->getServer()->getCraftingManager();
238 $recipe = $craftingManager->getCraftingRecipeFromIndex($recipeId);
239 if($recipe ===
null){
240 throw new ItemStackRequestProcessException(
"No such crafting recipe index: $recipeId");
243 $this->specialTransaction =
new CraftingTransaction($this->player, $craftingManager, [], $recipe, $repetitions);
249 $craftingResults = $recipe->getResultsFor($this->player->getCraftingGrid());
250 foreach($craftingResults as $k => $craftingResult){
251 $craftingResult->setCount($craftingResult->getCount() * $repetitions);
252 $this->craftingResults[$k] = $craftingResult;
254 if(count($this->craftingResults) === 1){
256 $this->setNextCreatedItem($this->craftingResults[array_key_first($this->craftingResults)]);
268 $createdItem = $this->nextCreatedItem;
269 if($createdItem ===
null){
273 if(!$this->createdItemFromCreativeInventory){
274 $availableCount = $createdItem->getCount() - $this->createdItemsTakenCount;
275 if($count > $availableCount){
276 throw new ItemStackRequestProcessException(
"Not enough created items available to be taken (have $availableCount, tried to take $count)");
280 $this->createdItemsTakenCount += $count;
281 $takenItem = clone $createdItem;
282 $takenItem->setCount($count);
283 if(!$this->createdItemFromCreativeInventory && $this->createdItemsTakenCount >= $createdItem->getCount()){
284 $this->setNextCreatedItem(
null);
310 $this->transferItems($action->getSource(), $action->getDestination(), $action->getCount());
312 $this->requestSlotInfos[] = $action->getSlot1();
313 $this->requestSlotInfos[] = $action->getSlot2();
315 [$inventory1, $slot1] = $this->getBuilderInventoryAndSlot($action->getSlot1());
316 [$inventory2, $slot2] = $this->getBuilderInventoryAndSlot($action->getSlot2());
318 $item1 = $inventory1->getItem($slot1);
319 $item2 = $inventory2->getItem($slot2);
320 $inventory1->setItem($slot1, $item2);
321 $inventory2->setItem($slot2, $item1);
322 }elseif($action instanceof DropStackRequestAction){
324 $dropped = $this->removeItemFromSlot($action->getSource(), $action->getCount());
325 $this->builder->addAction(
new DropItemAction($dropped));
327 }elseif($action instanceof DestroyStackRequestAction){
328 $destroyed = $this->removeItemFromSlot($action->getSource(), $action->getCount());
329 $this->builder->addAction(
new DestroyItemAction($destroyed));
331 }elseif($action instanceof CreativeCreateStackRequestAction){
332 $item = $this->player->getCreativeInventory()->getItem($action->getCreativeItemId());
334 throw new ItemStackRequestProcessException(
"No such creative item index: " . $action->getCreativeItemId());
337 $this->setNextCreatedItem($item,
true);
338 }elseif($action instanceof CraftRecipeStackRequestAction){
339 $window = $this->player->getCurrentWindow();
340 if($window instanceof EnchantInventory){
341 $optionId = $this->inventoryManager->getEnchantingTableOptionIndex($action->getRecipeId());
342 if($optionId !==
null && ($option = $window->getOption($optionId)) !==
null){
343 $this->specialTransaction =
new EnchantingTransaction($this->player, $option, $optionId + 1);
344 $this->setNextCreatedItem($window->getOutput($optionId));
347 $this->beginCrafting($action->getRecipeId(), $action->getRepetitions());
349 }elseif($action instanceof CraftRecipeAutoStackRequestAction){
350 $this->beginCrafting($action->getRecipeId(), $action->getRepetitions());
351 }elseif($action instanceof CraftingConsumeInputStackRequestAction){
352 $this->assertDoingCrafting();
353 $this->removeItemFromSlot($action->getSource(), $action->getCount());
355 }elseif($action instanceof CraftingCreateSpecificResultStackRequestAction){
356 $this->assertDoingCrafting();
358 $nextResultItem = $this->craftingResults[$action->getResultIndex()] ??
null;
359 if($nextResultItem ===
null){
360 throw new ItemStackRequestProcessException(
"No such crafting result index: " . $action->getResultIndex());
362 $this->setNextCreatedItem($nextResultItem);
363 }elseif($action instanceof DeprecatedCraftingResultsStackRequestAction){
366 throw new ItemStackRequestProcessException(
"Unhandled item stack request action");
374 foreach(
Utils::promoteKeys($this->request->getActions()) as $k => $action){
376 $this->processItemStackRequestAction($action);
378 throw new ItemStackRequestProcessException(
"Error processing action $k (" . (
new \ReflectionClass($action))->getShortName() .
"): " . $e->getMessage(), 0, $e);
381 $this->setNextCreatedItem(
null);
382 $inventoryActions = $this->builder->generateActions();
385 foreach($inventoryActions as $action){
386 $transaction->addAction($action);