ServerPlaceRecipe.java
net.minecraft.recipebook.ServerPlaceRecipe
信息
- 全限定名:net.minecraft.recipebook.ServerPlaceRecipe
- 类型:public class
- 包:net.minecraft.recipebook
- 源码路径:src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java
- 起始行号:L18
- 职责:
TODO
字段/常量
-
ITEM_NOT_FOUND- 类型:
int - 修饰符:
private static final - 源码定位:
L19 - 说明:
TODO
- 类型:
-
inventory- 类型:
Inventory - 修饰符:
private final - 源码定位:
L20 - 说明:
TODO
- 类型:
-
menu- 类型:
ServerPlaceRecipe.CraftingMenuAccess<R> - 修饰符:
private final - 源码定位:
L21 - 说明:
TODO
- 类型:
-
useMaxItems- 类型:
boolean - 修饰符:
private final - 源码定位:
L22 - 说明:
TODO
- 类型:
-
gridWidth- 类型:
int - 修饰符:
private final - 源码定位:
L23 - 说明:
TODO
- 类型:
-
gridHeight- 类型:
int - 修饰符:
private final - 源码定位:
L24 - 说明:
TODO
- 类型:
-
inputGridSlots- 类型:
List<Slot> - 修饰符:
private final - 源码定位:
L25 - 说明:
TODO
- 类型:
-
slotsToClear- 类型:
List<Slot> - 修饰符:
private final - 源码定位:
L26 - 说明:
TODO
- 类型:
内部类/嵌套类型
net.minecraft.recipebook.ServerPlaceRecipe.CraftingMenuAccess- 类型:
interface - 修饰符:
public - 源码定位:
L240 - 说明:
TODO
- 类型:
构造器
private ServerPlaceRecipe(ServerPlaceRecipe.CraftingMenuAccess<R> menu, Inventory inventory, boolean useMaxItems, int gridWidth, int gridHeight, List<Slot> inputGridSlots, List<Slot> slotsToClear) @ L50
- 构造器名:ServerPlaceRecipe
- 源码定位:L50
- 修饰符:private
参数:
- menu: ServerPlaceRecipe.CraftingMenuAccess
- inventory: Inventory
- useMaxItems: boolean
- gridWidth: int
- gridHeight: int
- inputGridSlots: List
- slotsToClear: List
说明:
TODO
方法
下面的方法块按源码顺序生成。
public static <I extends RecipeInput,R extends Recipe<I>> RecipeBookMenu.PostPlaceAction placeRecipe(ServerPlaceRecipe.CraftingMenuAccess<R> menu, int gridWidth, int gridHeight, List<Slot> inputGridSlots, List<Slot> slotsToClear, Inventory inventory, RecipeHolder<R> recipe, boolean useMaxItems, boolean allowDroppingItemsToClear) @ L28
- 方法名:placeRecipe
- 源码定位:L28
- 返回类型:<I extends RecipeInput,R extends Recipe> RecipeBookMenu.PostPlaceAction
- 修饰符:public static
参数:
- menu: ServerPlaceRecipe.CraftingMenuAccess
- gridWidth: int
- gridHeight: int
- inputGridSlots: List
- slotsToClear: List
- inventory: Inventory
- recipe: RecipeHolder
- useMaxItems: boolean
- allowDroppingItemsToClear: boolean
说明:
TODO
private RecipeBookMenu.PostPlaceAction tryPlaceRecipe(RecipeHolder<R> recipe, StackedItemContents availableItems) @ L68
- 方法名:tryPlaceRecipe
- 源码定位:L68
- 返回类型:RecipeBookMenu.PostPlaceAction
- 修饰符:private
参数:
- recipe: RecipeHolder
- availableItems: StackedItemContents
说明:
TODO
private void clearGrid() @ L80
- 方法名:clearGrid
- 源码定位:L80
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
private void placeRecipe(RecipeHolder<R> recipe, StackedItemContents availableItems) @ L90
- 方法名:placeRecipe
- 源码定位:L90
- 返回类型:void
- 修饰符:private
参数:
- recipe: RecipeHolder
- availableItems: StackedItemContents
说明:
TODO
private static int clampToMaxStackSize(int value, List<Holder<Item>> items) @ L137
- 方法名:clampToMaxStackSize
- 源码定位:L137
- 返回类型:int
- 修饰符:private static
参数:
- value: int
- items: List<Holder
- >
说明:
TODO
private int calculateAmountToCraft(int biggestCraftableStack, boolean recipeMatchesPlaced) @ L145
- 方法名:calculateAmountToCraft
- 源码定位:L145
- 返回类型:int
- 修饰符:private
参数:
- biggestCraftableStack: int
- recipeMatchesPlaced: boolean
说明:
TODO
private int moveItemToGrid(Slot targetSlot, Holder<Item> itemInInventory, int count) @ L168
- 方法名:moveItemToGrid
- 源码定位:L168
- 返回类型:int
- 修饰符:private
参数:
- targetSlot: Slot
- itemInInventory: Holder
- count: int
说明:
TODO
private boolean testClearGrid() @ L193
- 方法名:testClearGrid
- 源码定位:L193
- 返回类型:boolean
- 修饰符:private
参数:
- 无
说明:
TODO
private int getAmountOfFreeSlotsInInventory() @ L228
- 方法名:getAmountOfFreeSlotsInInventory
- 源码定位:L228
- 返回类型:int
- 修饰符:private
参数:
- 无
说明:
TODO
代码
public class ServerPlaceRecipe<R extends Recipe<?>> {
private static final int ITEM_NOT_FOUND = -1;
private final Inventory inventory;
private final ServerPlaceRecipe.CraftingMenuAccess<R> menu;
private final boolean useMaxItems;
private final int gridWidth;
private final int gridHeight;
private final List<Slot> inputGridSlots;
private final List<Slot> slotsToClear;
public static <I extends RecipeInput, R extends Recipe<I>> RecipeBookMenu.PostPlaceAction placeRecipe(
ServerPlaceRecipe.CraftingMenuAccess<R> menu,
int gridWidth,
int gridHeight,
List<Slot> inputGridSlots,
List<Slot> slotsToClear,
Inventory inventory,
RecipeHolder<R> recipe,
boolean useMaxItems,
boolean allowDroppingItemsToClear
) {
ServerPlaceRecipe<R> placer = new ServerPlaceRecipe<>(menu, inventory, useMaxItems, gridWidth, gridHeight, inputGridSlots, slotsToClear);
if (!allowDroppingItemsToClear && !placer.testClearGrid()) {
return RecipeBookMenu.PostPlaceAction.NOTHING;
} else {
StackedItemContents availableItems = new StackedItemContents();
inventory.fillStackedContents(availableItems);
menu.fillCraftSlotsStackedContents(availableItems);
return placer.tryPlaceRecipe(recipe, availableItems);
}
}
private ServerPlaceRecipe(
ServerPlaceRecipe.CraftingMenuAccess<R> menu,
Inventory inventory,
boolean useMaxItems,
int gridWidth,
int gridHeight,
List<Slot> inputGridSlots,
List<Slot> slotsToClear
) {
this.menu = menu;
this.inventory = inventory;
this.useMaxItems = useMaxItems;
this.gridWidth = gridWidth;
this.gridHeight = gridHeight;
this.inputGridSlots = inputGridSlots;
this.slotsToClear = slotsToClear;
}
private RecipeBookMenu.PostPlaceAction tryPlaceRecipe(RecipeHolder<R> recipe, StackedItemContents availableItems) {
if (availableItems.canCraft(recipe.value(), null)) {
this.placeRecipe(recipe, availableItems);
this.inventory.setChanged();
return RecipeBookMenu.PostPlaceAction.NOTHING;
} else {
this.clearGrid();
this.inventory.setChanged();
return RecipeBookMenu.PostPlaceAction.PLACE_GHOST_RECIPE;
}
}
private void clearGrid() {
for (Slot slot : this.slotsToClear) {
ItemStack itemStackCopy = slot.getItem().copy();
this.inventory.placeItemBackInInventory(itemStackCopy, false);
slot.set(itemStackCopy);
}
this.menu.clearCraftingContent();
}
private void placeRecipe(RecipeHolder<R> recipe, StackedItemContents availableItems) {
boolean recipeMatchesPlaced = this.menu.recipeMatches(recipe);
int biggestCraftableStack = availableItems.getBiggestCraftableStack(recipe.value(), null);
if (recipeMatchesPlaced) {
for (Slot inputSlot : this.inputGridSlots) {
ItemStack itemStack = inputSlot.getItem();
if (!itemStack.isEmpty() && Math.min(biggestCraftableStack, itemStack.getMaxStackSize()) < itemStack.getCount() + 1) {
return;
}
}
}
int amountToCraft = this.calculateAmountToCraft(biggestCraftableStack, recipeMatchesPlaced);
List<Holder<Item>> itemsUsedPerIngredient = new ArrayList<>();
if (availableItems.canCraft(recipe.value(), amountToCraft, itemsUsedPerIngredient::add)) {
int adjustedAmountToCraft = clampToMaxStackSize(amountToCraft, itemsUsedPerIngredient);
if (adjustedAmountToCraft != amountToCraft) {
itemsUsedPerIngredient.clear();
if (!availableItems.canCraft(recipe.value(), adjustedAmountToCraft, itemsUsedPerIngredient::add)) {
return;
}
}
this.clearGrid();
PlaceRecipeHelper.placeRecipe(
this.gridWidth,
this.gridHeight,
recipe.value(),
recipe.value().placementInfo().slotsToIngredientIndex(),
(ingredientIndex, gridIndex, gridXPos, gridYPos) -> {
if (ingredientIndex != -1) {
Slot targetGridSlot = this.inputGridSlots.get(gridIndex);
Holder<Item> itemUsed = itemsUsedPerIngredient.get(ingredientIndex);
int remainingCount = adjustedAmountToCraft;
while (remainingCount > 0) {
remainingCount = this.moveItemToGrid(targetGridSlot, itemUsed, remainingCount);
if (remainingCount == -1) {
return;
}
}
}
}
);
}
}
private static int clampToMaxStackSize(int value, List<Holder<Item>> items) {
for (Holder<Item> item : items) {
value = Math.min(value, item.components().getOrDefault(DataComponents.MAX_STACK_SIZE, 1));
}
return value;
}
private int calculateAmountToCraft(int biggestCraftableStack, boolean recipeMatchesPlaced) {
if (this.useMaxItems) {
return biggestCraftableStack;
} else if (recipeMatchesPlaced) {
int smallestStackSize = Integer.MAX_VALUE;
for (Slot inputSlot : this.inputGridSlots) {
ItemStack itemStack = inputSlot.getItem();
if (!itemStack.isEmpty() && smallestStackSize > itemStack.getCount()) {
smallestStackSize = itemStack.getCount();
}
}
if (smallestStackSize != Integer.MAX_VALUE) {
smallestStackSize++;
}
return smallestStackSize;
} else {
return 1;
}
}
private int moveItemToGrid(Slot targetSlot, Holder<Item> itemInInventory, int count) {
ItemStack itemInTargetSlot = targetSlot.getItem();
int inventorySlotId = this.inventory.findSlotMatchingCraftingIngredient(itemInInventory, itemInTargetSlot);
if (inventorySlotId == -1) {
return -1;
} else {
ItemStack inventoryItem = this.inventory.getItem(inventorySlotId);
ItemStack takenStack;
if (count < inventoryItem.getCount()) {
takenStack = this.inventory.removeItem(inventorySlotId, count);
} else {
takenStack = this.inventory.removeItemNoUpdate(inventorySlotId);
}
int takenCount = takenStack.getCount();
if (itemInTargetSlot.isEmpty()) {
targetSlot.set(takenStack);
} else {
itemInTargetSlot.grow(takenCount);
}
return count - takenCount;
}
}
private boolean testClearGrid() {
List<ItemStack> freeSlots = Lists.newArrayList();
int freeSlotsInInventory = this.getAmountOfFreeSlotsInInventory();
for (Slot inputSlot : this.inputGridSlots) {
ItemStack itemStack = inputSlot.getItem().copy();
if (!itemStack.isEmpty()) {
int slotId = this.inventory.getSlotWithRemainingSpace(itemStack);
if (slotId == -1 && freeSlots.size() <= freeSlotsInInventory) {
for (ItemStack itemStackInList : freeSlots) {
if (ItemStack.isSameItem(itemStackInList, itemStack)
&& itemStackInList.getCount() != itemStackInList.getMaxStackSize()
&& itemStackInList.getCount() + itemStack.getCount() <= itemStackInList.getMaxStackSize()) {
itemStackInList.grow(itemStack.getCount());
itemStack.setCount(0);
break;
}
}
if (!itemStack.isEmpty()) {
if (freeSlots.size() >= freeSlotsInInventory) {
return false;
}
freeSlots.add(itemStack);
}
} else if (slotId == -1) {
return false;
}
}
}
return true;
}
private int getAmountOfFreeSlotsInInventory() {
int freeSlots = 0;
for (ItemStack item : this.inventory.getNonEquipmentItems()) {
if (item.isEmpty()) {
freeSlots++;
}
}
return freeSlots;
}
public interface CraftingMenuAccess<T extends Recipe<?>> {
void fillCraftSlotsStackedContents(StackedItemContents stackedContents);
void clearCraftingContent();
boolean recipeMatches(RecipeHolder<T> recipe);
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
PlaceRecipeHelper.placeRecipe()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/构造调用 - 关联成员:
StackedItemContents()
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ItemStack.isSameItem()
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
返回值
- 引用位置: