Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
Re-implement on-the-fly recipe sending
Dieser Commit ist enthalten in:
Ursprung
344d40dd1f
Commit
05f153c941
@ -29,6 +29,7 @@ import lombok.*;
|
|||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.item.Items;
|
import org.geysermc.geyser.item.Items;
|
||||||
import org.geysermc.geyser.item.type.Item;
|
import org.geysermc.geyser.item.type.Item;
|
||||||
import org.geysermc.geyser.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
@ -38,6 +39,10 @@ import org.geysermc.geyser.translator.item.ItemTranslator;
|
|||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemStackSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@ -77,6 +82,20 @@ public class GeyserItemStack {
|
|||||||
return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents());
|
return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @NonNull GeyserItemStack from(@NonNull SlotDisplay slotDisplay) {
|
||||||
|
if (slotDisplay instanceof EmptySlotDisplay) {
|
||||||
|
return GeyserItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof ItemSlotDisplay itemSlotDisplay) {
|
||||||
|
return GeyserItemStack.of(itemSlotDisplay.item(), 1);
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof ItemStackSlotDisplay itemStackSlotDisplay) {
|
||||||
|
return GeyserItemStack.from(itemStackSlotDisplay.itemStack());
|
||||||
|
}
|
||||||
|
GeyserImpl.getInstance().getLogger().warning("Unsure how to convert to ItemStack: " + slotDisplay);
|
||||||
|
return GeyserItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
public int getJavaId() {
|
public int getJavaId() {
|
||||||
return isEmpty() ? 0 : javaId;
|
return isEmpty() ? 0 : javaId;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
package org.geysermc.geyser.inventory.recipe;
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A more compact version of {link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}.
|
* A more compact version of {link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}.
|
||||||
@ -38,5 +38,5 @@ public interface GeyserRecipe {
|
|||||||
boolean isShaped();
|
boolean isShaped();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
ItemStack result();
|
SlotDisplay result();
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,16 @@
|
|||||||
package org.geysermc.geyser.inventory.recipe;
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapedCraftingRecipeDisplay;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
|
||||||
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
|
import java.util.List;
|
||||||
|
|
||||||
// public GeyserShapedRecipe(ShapedRecipeData data) {
|
public record GeyserShapedRecipe(int width, int height, List<SlotDisplay> ingredients, @Nullable SlotDisplay result) implements GeyserRecipe {
|
||||||
// this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult());
|
|
||||||
// }
|
public GeyserShapedRecipe(ShapedCraftingRecipeDisplay data) {
|
||||||
|
this(data.width(), data.height(), data.ingredients(), data.result());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isShaped() {
|
public boolean isShaped() {
|
||||||
|
@ -26,14 +26,16 @@
|
|||||||
package org.geysermc.geyser.inventory.recipe;
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapelessCraftingRecipeDisplay;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
|
||||||
public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
|
import java.util.List;
|
||||||
|
|
||||||
// public GeyserShapelessRecipe(ShapelessRecipeData data) {
|
public record GeyserShapelessRecipe(List<SlotDisplay> ingredients, @Nullable SlotDisplay result) implements GeyserRecipe {
|
||||||
// this(data.getIngredients(), data.getResult());
|
|
||||||
// }
|
public GeyserShapelessRecipe(ShapelessCraftingRecipeDisplay data) {
|
||||||
|
this(data.ingredients(), data.result());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isShaped() {
|
public boolean isShaped() {
|
||||||
|
@ -31,8 +31,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtType;
|
import org.cloudburstmc.nbt.NbtType;
|
||||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||||
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
|
|
||||||
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||||
@ -92,7 +90,7 @@ public abstract class RecipeRegistryLoader implements RegistryLoader<String, Map
|
|||||||
for (int i = 0; i < rawInputs.size(); i++) {
|
for (int i = 0; i < rawInputs.size(); i++) {
|
||||||
//javaInputs[i] = new Ingredient(new ItemStack[] {toItemStack(rawInputs.get(i), helper)});
|
//javaInputs[i] = new Ingredient(new ItemStack[] {toItemStack(rawInputs.get(i), helper)});
|
||||||
}
|
}
|
||||||
deserializedRecipes.add(new GeyserShapelessRecipe(javaInputs, output));
|
//deserializedRecipes.add(new GeyserShapelessRecipe(javaInputs, output));
|
||||||
}
|
}
|
||||||
return deserializedRecipes;
|
return deserializedRecipes;
|
||||||
}
|
}
|
||||||
@ -118,7 +116,7 @@ public abstract class RecipeRegistryLoader implements RegistryLoader<String, Map
|
|||||||
//inputs[i++] = new Ingredient(new ItemStack[] {stack});
|
//inputs[i++] = new Ingredient(new ItemStack[] {stack});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deserializedRecipes.add(new GeyserShapedRecipe(shape.size(), shape.get(0).length, inputs, output));
|
//deserializedRecipes.add(new GeyserShapedRecipe(shape.size(), shape.get(0).length, inputs, output));
|
||||||
}
|
}
|
||||||
return deserializedRecipes;
|
return deserializedRecipes;
|
||||||
}
|
}
|
||||||
|
@ -446,8 +446,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
*/
|
*/
|
||||||
private final Int2ObjectMap<List<String>> javaToBedrockRecipeIds;
|
private final Int2ObjectMap<List<String>> javaToBedrockRecipeIds;
|
||||||
|
|
||||||
@Setter
|
private final Int2ObjectMap<GeyserRecipe> craftingRecipes;
|
||||||
private Int2ObjectMap<GeyserRecipe> craftingRecipes;
|
|
||||||
private final AtomicInteger lastRecipeNetId;
|
private final AtomicInteger lastRecipeNetId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,21 +25,40 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.translator.inventory;
|
package org.geysermc.geyser.translator.inventory;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSortedSet;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.*;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.AutoCraftRecipeAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ConsumeAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftResultsDeprecatedAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.DropAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.SwapAction;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.TransferItemStackRequestAction;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseContainer;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseContainer;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseSlot;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseSlot;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseStatus;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseStatus;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.ItemStackResponsePacket;
|
import org.cloudburstmc.protocol.bedrock.packet.ItemStackResponsePacket;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.inventory.*;
|
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||||
|
import org.geysermc.geyser.inventory.CartographyContainer;
|
||||||
|
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||||
|
import org.geysermc.geyser.inventory.Inventory;
|
||||||
|
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||||
|
import org.geysermc.geyser.inventory.SlotType;
|
||||||
import org.geysermc.geyser.inventory.click.Click;
|
import org.geysermc.geyser.inventory.click.Click;
|
||||||
import org.geysermc.geyser.inventory.click.ClickPlan;
|
import org.geysermc.geyser.inventory.click.ClickPlan;
|
||||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||||
@ -56,12 +75,17 @@ import org.geysermc.geyser.translator.inventory.furnace.SmokerInventoryTranslato
|
|||||||
import org.geysermc.geyser.util.InventoryUtils;
|
import org.geysermc.geyser.util.InventoryUtils;
|
||||||
import org.geysermc.geyser.util.ItemUtils;
|
import org.geysermc.geyser.util.ItemUtils;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public abstract class InventoryTranslator {
|
public abstract class InventoryTranslator {
|
||||||
@ -642,8 +666,8 @@ public abstract class InventoryTranslator {
|
|||||||
}
|
}
|
||||||
int gridDimensions = gridSize == 4 ? 2 : 3;
|
int gridDimensions = gridSize == 4 ? 2 : 3;
|
||||||
|
|
||||||
Ingredient[] ingredients = new Ingredient[0];
|
List<SlotDisplay> ingredients = Collections.emptyList();
|
||||||
ItemStack output = null;
|
SlotDisplay output = null;
|
||||||
int recipeWidth = 0;
|
int recipeWidth = 0;
|
||||||
int ingRemaining = 0;
|
int ingRemaining = 0;
|
||||||
int ingredientIndex = -1;
|
int ingredientIndex = -1;
|
||||||
@ -697,7 +721,7 @@ public abstract class InventoryTranslator {
|
|||||||
ingredients = shapelessRecipe.ingredients();
|
ingredients = shapelessRecipe.ingredients();
|
||||||
recipeWidth = gridDimensions;
|
recipeWidth = gridDimensions;
|
||||||
output = shapelessRecipe.result();
|
output = shapelessRecipe.result();
|
||||||
if (ingredients.length > gridSize) {
|
if (ingredients.size() > gridSize) {
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,11 +752,11 @@ public abstract class InventoryTranslator {
|
|||||||
craftState = CraftState.INGREDIENTS;
|
craftState = CraftState.INGREDIENTS;
|
||||||
|
|
||||||
if (ingRemaining == 0) {
|
if (ingRemaining == 0) {
|
||||||
while (++ingredientIndex < ingredients.length) {
|
while (++ingredientIndex < ingredients.size()) {
|
||||||
// if (ingredients[ingredientIndex].getOptions().length != 0) {
|
if (!(ingredients.get(ingredientIndex) instanceof EmptySlotDisplay)) { // TODO I guess can technically other options be empty?
|
||||||
// ingRemaining = timesCrafted;
|
ingRemaining = timesCrafted;
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ import java.util.UUID;
|
|||||||
import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID;
|
import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID;
|
||||||
|
|
||||||
@Translator(packet = ClientboundFinishConfigurationPacket.class)
|
@Translator(packet = ClientboundFinishConfigurationPacket.class)
|
||||||
public class JavaFinishConfigurationPacketTranslator extends PacketTranslator<ClientboundFinishConfigurationPacket> {
|
public class JavaFinishConfigurationTranslator extends PacketTranslator<ClientboundFinishConfigurationPacket> {
|
||||||
/**
|
/**
|
||||||
* Required to use the specified cartography table recipes
|
* Required to use the specified cartography table recipes
|
||||||
*/
|
*/
|
||||||
@ -72,6 +72,9 @@ public class JavaFinishConfigurationPacketTranslator extends PacketTranslator<Cl
|
|||||||
craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.forVersion(session.getUpstream().getProtocolVersion()));
|
craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.forVersion(session.getUpstream().getProtocolVersion()));
|
||||||
if (session.isSentSpawnPacket()) {
|
if (session.isSentSpawnPacket()) {
|
||||||
session.getUpstream().sendPacket(craftingDataPacket);
|
session.getUpstream().sendPacket(craftingDataPacket);
|
||||||
|
session.getCraftingRecipes().clear();
|
||||||
|
session.getJavaToBedrockRecipeIds().clear();
|
||||||
|
session.getStonecutterRecipes().clear();
|
||||||
} else {
|
} else {
|
||||||
session.getUpstream().queuePostStartGamePacket(craftingDataPacket);
|
session.getUpstream().queuePostStartGamePacket(craftingDataPacket);
|
||||||
}
|
}
|
@ -39,6 +39,9 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescri
|
|||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UnlockedRecipesPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UnlockedRecipesPacket;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
||||||
import org.geysermc.geyser.item.Items;
|
import org.geysermc.geyser.item.Items;
|
||||||
import org.geysermc.geyser.item.type.BedrockRequiresTagItem;
|
import org.geysermc.geyser.item.type.BedrockRequiresTagItem;
|
||||||
import org.geysermc.geyser.item.type.Item;
|
import org.geysermc.geyser.item.type.Item;
|
||||||
@ -79,9 +82,10 @@ public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRec
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, ClientboundRecipeBookAddPacket packet) {
|
public void translate(GeyserSession session, ClientboundRecipeBookAddPacket packet) {
|
||||||
//System.out.println(packet);
|
System.out.println(packet);
|
||||||
int netId = session.getLastRecipeNetId().get();
|
int netId = session.getLastRecipeNetId().get();
|
||||||
Int2ObjectMap<List<String>> javaToBedrockRecipeIds = session.getJavaToBedrockRecipeIds();
|
Int2ObjectMap<List<String>> javaToBedrockRecipeIds = session.getJavaToBedrockRecipeIds();
|
||||||
|
Int2ObjectMap<GeyserRecipe> geyserRecipes = session.getCraftingRecipes();
|
||||||
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
||||||
|
|
||||||
UnlockedRecipesPacket recipesPacket = new UnlockedRecipesPacket();
|
UnlockedRecipesPacket recipesPacket = new UnlockedRecipesPacket();
|
||||||
@ -101,14 +105,17 @@ public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRec
|
|||||||
List<String> bedrockRecipeIds = new ArrayList<>();
|
List<String> bedrockRecipeIds = new ArrayList<>();
|
||||||
ItemData output = bedrockRecipes.right();
|
ItemData output = bedrockRecipes.right();
|
||||||
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
|
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
|
||||||
|
GeyserRecipe geyserRecipe = new GeyserShapedRecipe(shapedRecipe);
|
||||||
for (int i = 0; i < left.size(); i++) {
|
for (int i = 0; i < left.size(); i++) {
|
||||||
List<ItemDescriptorWithCount> inputs = left.get(i);
|
List<ItemDescriptorWithCount> inputs = left.get(i);
|
||||||
String recipeId = contents.id() + "_" + i;
|
String recipeId = contents.id() + "_" + i;
|
||||||
|
int recipeNetworkId = netId++;
|
||||||
craftingDataPacket.getCraftingData().add(ShapedRecipeData.shaped(recipeId,
|
craftingDataPacket.getCraftingData().add(ShapedRecipeData.shaped(recipeId,
|
||||||
shapedRecipe.width(), shapedRecipe.height(), inputs,
|
shapedRecipe.width(), shapedRecipe.height(), inputs,
|
||||||
Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0, netId++, false, RecipeUnlockingRequirement.INVALID));
|
Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0, recipeNetworkId, false, RecipeUnlockingRequirement.INVALID));
|
||||||
recipesPacket.getUnlockedRecipes().add(recipeId);
|
recipesPacket.getUnlockedRecipes().add(recipeId);
|
||||||
bedrockRecipeIds.add(recipeId);
|
bedrockRecipeIds.add(recipeId);
|
||||||
|
geyserRecipes.put(recipeNetworkId, geyserRecipe);
|
||||||
}
|
}
|
||||||
javaToBedrockRecipeIds.put(contents.id(), List.copyOf(bedrockRecipeIds));
|
javaToBedrockRecipeIds.put(contents.id(), List.copyOf(bedrockRecipeIds));
|
||||||
}
|
}
|
||||||
@ -121,13 +128,16 @@ public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRec
|
|||||||
List<String> bedrockRecipeIds = new ArrayList<>();
|
List<String> bedrockRecipeIds = new ArrayList<>();
|
||||||
ItemData output = bedrockRecipes.right();
|
ItemData output = bedrockRecipes.right();
|
||||||
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
|
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
|
||||||
|
GeyserRecipe geyserRecipe = new GeyserShapelessRecipe(shapelessRecipe);
|
||||||
for (int i = 0; i < left.size(); i++) {
|
for (int i = 0; i < left.size(); i++) {
|
||||||
List<ItemDescriptorWithCount> inputs = left.get(i);
|
List<ItemDescriptorWithCount> inputs = left.get(i);
|
||||||
String recipeId = contents.id() + "_" + i;
|
String recipeId = contents.id() + "_" + i;
|
||||||
|
int recipeNetworkId = netId++;
|
||||||
craftingDataPacket.getCraftingData().add(ShapelessRecipeData.shapeless(recipeId,
|
craftingDataPacket.getCraftingData().add(ShapelessRecipeData.shapeless(recipeId,
|
||||||
inputs, Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0, netId++, RecipeUnlockingRequirement.INVALID));
|
inputs, Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0, recipeNetworkId, RecipeUnlockingRequirement.INVALID));
|
||||||
recipesPacket.getUnlockedRecipes().add(recipeId);
|
recipesPacket.getUnlockedRecipes().add(recipeId);
|
||||||
bedrockRecipeIds.add(recipeId);
|
bedrockRecipeIds.add(recipeId);
|
||||||
|
geyserRecipes.put(recipeNetworkId, geyserRecipe);
|
||||||
}
|
}
|
||||||
javaToBedrockRecipeIds.put(contents.id(), List.copyOf(bedrockRecipeIds));
|
javaToBedrockRecipeIds.put(contents.id(), List.copyOf(bedrockRecipeIds));
|
||||||
}
|
}
|
||||||
|
@ -44,12 +44,15 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
|||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
import org.geysermc.geyser.util.InventoryUtils;
|
import org.geysermc.geyser.util.InventoryUtils;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemStackSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -104,9 +107,6 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||||||
* Checks for a changed output slot in the crafting grid, and ensures Bedrock sees the recipe.
|
* Checks for a changed output slot in the crafting grid, and ensures Bedrock sees the recipe.
|
||||||
*/
|
*/
|
||||||
private static void updateCraftingGrid(GeyserSession session, int slot, ItemStack item, Inventory inventory, InventoryTranslator translator) {
|
private static void updateCraftingGrid(GeyserSession session, int slot, ItemStack item, Inventory inventory, InventoryTranslator translator) {
|
||||||
if (true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check if it's the crafting grid result slot.
|
// Check if it's the crafting grid result slot.
|
||||||
if (slot != 0) {
|
if (slot != 0) {
|
||||||
return;
|
return;
|
||||||
@ -166,14 +166,13 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||||||
|
|
||||||
ItemData[] ingredients = new ItemData[height * width];
|
ItemData[] ingredients = new ItemData[height * width];
|
||||||
//construct ingredient list and clear slots on client
|
//construct ingredient list and clear slots on client
|
||||||
Ingredient[] javaIngredients = new Ingredient[height * width];
|
List<SlotDisplay> javaIngredients = new ArrayList<>(height * width);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int row = firstRow; row < height + firstRow; row++) {
|
for (int row = firstRow; row < height + firstRow; row++) {
|
||||||
for (int col = firstCol; col < width + firstCol; col++) {
|
for (int col = firstCol; col < width + firstCol; col++) {
|
||||||
GeyserItemStack geyserItemStack = inventory.getItem(col + (row * gridDimensions) + 1);
|
GeyserItemStack geyserItemStack = inventory.getItem(col + (row * gridDimensions) + 1);
|
||||||
ingredients[index] = geyserItemStack.getItemData(session);
|
ingredients[index] = geyserItemStack.getItemData(session);
|
||||||
int[] items = new int[] {geyserItemStack.isEmpty() ? 0 : geyserItemStack.getJavaId()};
|
javaIngredients.add(geyserItemStack.isEmpty() ? new EmptySlotDisplay() : new ItemStackSlotDisplay(geyserItemStack.getItemStack()));
|
||||||
javaIngredients[index] = new Ingredient(new HolderSet(items));
|
|
||||||
|
|
||||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||||
slotPacket.setContainerId(ContainerId.UI);
|
slotPacket.setContainerId(ContainerId.UI);
|
||||||
@ -185,7 +184,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache this recipe so we know the client has received it
|
// Cache this recipe so we know the client has received it
|
||||||
session.getCraftingRecipes().put(newRecipeId, new GeyserShapedRecipe(width, height, javaIngredients, item));
|
session.getCraftingRecipes().put(newRecipeId, new GeyserShapedRecipe(width, height, javaIngredients, new ItemStackSlotDisplay(item)));
|
||||||
|
|
||||||
CraftingDataPacket craftPacket = new CraftingDataPacket();
|
CraftingDataPacket craftPacket = new CraftingDataPacket();
|
||||||
craftPacket.getCraftingData().add(ShapedRecipeData.shaped(
|
craftPacket.getCraftingData().add(ShapedRecipeData.shaped(
|
||||||
|
@ -51,6 +51,8 @@ import org.geysermc.geyser.level.BedrockDimension;
|
|||||||
import org.geysermc.geyser.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||||
|
import org.geysermc.geyser.session.cache.tags.Tag;
|
||||||
import org.geysermc.geyser.text.ChatColor;
|
import org.geysermc.geyser.text.ChatColor;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||||
@ -59,15 +61,21 @@ import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTransl
|
|||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.CompositeSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemStackSlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.TagSlotDisplay;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
@ -441,6 +449,35 @@ public class InventoryUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the provided item stack would be accepted by the slot display.
|
||||||
|
*/
|
||||||
|
public static boolean acceptsAsInput(GeyserSession session, SlotDisplay slotDisplay, GeyserItemStack itemStack) {
|
||||||
|
if (slotDisplay instanceof EmptySlotDisplay) {
|
||||||
|
return itemStack.isEmpty();
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof CompositeSlotDisplay compositeSlotDisplay) {
|
||||||
|
if (compositeSlotDisplay.contents().size() == 1) {
|
||||||
|
return acceptsAsInput(session, compositeSlotDisplay.contents().get(0), itemStack);
|
||||||
|
}
|
||||||
|
return compositeSlotDisplay.contents().stream().anyMatch(aSlotDisplay -> acceptsAsInput(session, aSlotDisplay, itemStack));
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof ItemSlotDisplay itemSlotDisplay) {
|
||||||
|
return itemStack.getJavaId() == itemSlotDisplay.item();
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof ItemStackSlotDisplay itemStackSlotDisplay) {
|
||||||
|
ItemStack other = itemStackSlotDisplay.itemStack();
|
||||||
|
// Amount check might be flimsy?
|
||||||
|
return itemStack.getJavaId() == other.getId() && itemStack.getAmount() >= other.getAmount()
|
||||||
|
&& Objects.equals(itemStack.getComponents(), other.getDataComponents());
|
||||||
|
}
|
||||||
|
if (slotDisplay instanceof TagSlotDisplay tagSlotDisplay) {
|
||||||
|
return session.getTagCache().is(new Tag<>(JavaRegistries.ITEM, tagSlotDisplay.tag()), itemStack.asItem());
|
||||||
|
}
|
||||||
|
session.getGeyser().getLogger().warning("Unknown slot display type: " + slotDisplay);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test all known recipes to find a valid match
|
* Test all known recipes to find a valid match
|
||||||
*
|
*
|
||||||
@ -462,53 +499,46 @@ public class InventoryUtils {
|
|||||||
for (GeyserRecipe recipe : session.getCraftingRecipes().values()) {
|
for (GeyserRecipe recipe : session.getCraftingRecipes().values()) {
|
||||||
if (recipe.isShaped()) {
|
if (recipe.isShaped()) {
|
||||||
GeyserShapedRecipe shapedRecipe = (GeyserShapedRecipe) recipe;
|
GeyserShapedRecipe shapedRecipe = (GeyserShapedRecipe) recipe;
|
||||||
if (output != null && !shapedRecipe.result().equals(output)) {
|
if (output != null && !acceptsAsInput(session, shapedRecipe.result(), GeyserItemStack.from(output))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ingredient[] ingredients = shapedRecipe.ingredients();
|
List<SlotDisplay> ingredients = shapedRecipe.ingredients();
|
||||||
if (shapedRecipe.width() != width || shapedRecipe.height() != height || width * height != ingredients.length) {
|
if (shapedRecipe.width() != width || shapedRecipe.height() != height || width * height != ingredients.size()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!testShapedRecipe(ingredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) {
|
if (!testShapedRecipe(session, ingredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) {
|
||||||
Ingredient[] mirroredIngredients = new Ingredient[ingredients.length];
|
List<SlotDisplay> mirroredIngredients = new ArrayList<>(ingredients.size());
|
||||||
for (int row = 0; row < height; row++) {
|
for (int row = 0; row < height; row++) {
|
||||||
for (int col = 0; col < width; col++) {
|
for (int col = 0; col < width; col++) {
|
||||||
mirroredIngredients[col + (row * width)] = ingredients[(width - 1 - col) + (row * width)];
|
mirroredIngredients.add(ingredients.get((width - 1 - col) + (row * width)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Arrays.equals(ingredients, mirroredIngredients) ||
|
if (!ingredients.equals(mirroredIngredients) ||
|
||||||
!testShapedRecipe(mirroredIngredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) {
|
!testShapedRecipe(session, mirroredIngredients, inventoryGetter, gridDimensions, firstRow, height, firstCol, width)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GeyserShapelessRecipe data = (GeyserShapelessRecipe) recipe;
|
GeyserShapelessRecipe data = (GeyserShapelessRecipe) recipe;
|
||||||
if (output != null && !data.result().equals(output)) {
|
if (output != null && !acceptsAsInput(session, data.result(), GeyserItemStack.from(output))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (nonAirCount != data.ingredients().length) {
|
if (nonAirCount != data.ingredients().size()) {
|
||||||
// There is an amount of items on the crafting table that is not the same as the ingredient count so this is invalid
|
// There is an amount of items on the crafting table that is not the same as the ingredient count so this is invalid
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < data.ingredients().length; i++) {
|
for (int i = 0; i < data.ingredients().size(); i++) {
|
||||||
Ingredient ingredient = data.ingredients()[i];
|
SlotDisplay slotDisplay = data.ingredients().get(i);
|
||||||
for (int item : ingredient.getValues().getHolders()) { // FIXME
|
|
||||||
boolean inventoryHasItem = false;
|
boolean inventoryHasItem = false;
|
||||||
// Iterate only over the crafting table to find this item
|
// Iterate only over the crafting table to find this item
|
||||||
crafting:
|
|
||||||
for (int row = firstRow; row < height + firstRow; row++) {
|
for (int row = firstRow; row < height + firstRow; row++) {
|
||||||
for (int col = firstCol; col < width + firstCol; col++) {
|
for (int col = firstCol; col < width + firstCol; col++) {
|
||||||
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
|
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
|
||||||
if (geyserItemStack.isEmpty()) {
|
if (acceptsAsInput(session, slotDisplay, geyserItemStack)) {
|
||||||
inventoryHasItem = item == 0;
|
|
||||||
if (inventoryHasItem) {
|
|
||||||
break crafting;
|
|
||||||
}
|
|
||||||
} else if (item == geyserItemStack.getJavaId()) {
|
|
||||||
inventoryHasItem = true;
|
inventoryHasItem = true;
|
||||||
break crafting;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,37 +547,23 @@ public class InventoryUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
System.out.println("Found existing match for item: " + recipe);
|
||||||
return recipe;
|
return recipe;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
private static boolean testShapedRecipe(final Ingredient[] ingredients, final IntFunction<GeyserItemStack> inventoryGetter,
|
private static boolean testShapedRecipe(final GeyserSession session, final List<SlotDisplay> ingredients, final IntFunction<GeyserItemStack> inventoryGetter,
|
||||||
final int gridDimensions, final int firstRow, final int height, final int firstCol, final int width) {
|
final int gridDimensions, final int firstRow, final int height, final int firstCol, final int width) {
|
||||||
int ingredientIndex = 0;
|
int ingredientIndex = 0;
|
||||||
for (int row = firstRow; row < height + firstRow; row++) {
|
for (int row = firstRow; row < height + firstRow; row++) {
|
||||||
for (int col = firstCol; col < width + firstCol; col++) {
|
for (int col = firstCol; col < width + firstCol; col++) {
|
||||||
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
|
GeyserItemStack geyserItemStack = inventoryGetter.apply(col + (row * gridDimensions) + 1);
|
||||||
Ingredient ingredient = ingredients[ingredientIndex++];
|
SlotDisplay slotDisplay = ingredients.get(ingredientIndex++);
|
||||||
int[] items = ingredient.getValues().getHolders(); // FIXME
|
if (!acceptsAsInput(session, slotDisplay, geyserItemStack)) {
|
||||||
if (items.length == 0) {
|
|
||||||
if (!geyserItemStack.isEmpty()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
boolean inventoryHasItem = false;
|
|
||||||
for (int item : items) {
|
|
||||||
if (geyserItemStack.getJavaId() == item) {
|
|
||||||
inventoryHasItem = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!inventoryHasItem) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren