use of com.github.steveice10.mc.protocol.data.game.recipe.Ingredient in project Geyser by GeyserMC.
the class JavaContainerSetSlotTranslator method updateCraftingGrid.
/**
* 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) {
if (slot != 0) {
return;
}
int gridSize = translator.getGridSize();
if (gridSize == -1) {
return;
}
if (item == null || item.getId() == 0) {
return;
}
session.setCraftingGridFuture(session.scheduleInEventLoop(() -> {
int offset = gridSize == 4 ? 28 : 32;
int gridDimensions = gridSize == 4 ? 2 : 3;
int firstRow = -1, height = -1;
int firstCol = -1, width = -1;
for (int row = 0; row < gridDimensions; row++) {
for (int col = 0; col < gridDimensions; col++) {
if (!inventory.getItem(col + (row * gridDimensions) + 1).isEmpty()) {
if (firstRow == -1) {
firstRow = row;
firstCol = col;
} else {
firstCol = Math.min(firstCol, col);
}
height = Math.max(height, row);
width = Math.max(width, col);
}
}
}
// empty grid
if (firstRow == -1) {
return;
}
height += -firstRow + 1;
width += -firstCol + 1;
if (InventoryUtils.getValidRecipe(session, item, inventory::getItem, gridDimensions, firstRow, height, firstCol, width) != null) {
// Recipe is already present on the client; don't send packet
return;
}
UUID uuid = UUID.randomUUID();
int newRecipeId = session.getLastRecipeNetId().incrementAndGet();
ItemData[] ingredients = new ItemData[height * width];
// construct ingredient list and clear slots on client
Ingredient[] javaIngredients = new Ingredient[height * width];
int index = 0;
for (int row = firstRow; row < height + firstRow; row++) {
for (int col = firstCol; col < width + firstCol; col++) {
GeyserItemStack geyserItemStack = inventory.getItem(col + (row * gridDimensions) + 1);
ingredients[index] = geyserItemStack.getItemData(session);
ItemStack[] itemStacks = new ItemStack[] { geyserItemStack.isEmpty() ? null : geyserItemStack.getItemStack(1) };
javaIngredients[index] = new Ingredient(itemStacks);
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(col + (row * gridDimensions) + offset);
slotPacket.setItem(ItemData.AIR);
session.sendUpstreamPacket(slotPacket);
index++;
}
}
// Cache this recipe so we know the client has received it
session.getCraftingRecipes().put(newRecipeId, new GeyserShapedRecipe(width, height, javaIngredients, item));
CraftingDataPacket craftPacket = new CraftingDataPacket();
craftPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(), width, height, Arrays.asList(ingredients), Collections.singletonList(ItemTranslator.translateToBedrock(session, item)), uuid, "crafting_table", 0, newRecipeId));
craftPacket.setCleanRecipes(false);
session.sendUpstreamPacket(craftPacket);
index = 0;
for (int row = firstRow; row < height + firstRow; row++) {
for (int col = firstCol; col < width + firstCol; col++) {
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(col + (row * gridDimensions) + offset);
slotPacket.setItem(ingredients[index]);
session.sendUpstreamPacket(slotPacket);
index++;
}
}
}, 150, TimeUnit.MILLISECONDS));
}
use of com.github.steveice10.mc.protocol.data.game.recipe.Ingredient in project Geyser by GeyserMC.
the class RecipeRegistryPopulator method getCraftingDataFromJsonNode.
/**
* Computes a Bedrock crafting recipe from the given JSON data.
* @param node the JSON data to compute
* @param recipes a list of all the recipes
* @return the {@link CraftingData} to send to the Bedrock client.
*/
private static CraftingData getCraftingDataFromJsonNode(JsonNode node, Int2ObjectMap<GeyserRecipe> recipes, ItemMappings mappings) {
int netId = ++LAST_RECIPE_NET_ID;
int type = node.get("bedrockRecipeType").asInt();
JsonNode outputNode = node.get("output");
ItemMapping outputEntry = mappings.getMapping(outputNode.get("identifier").asText());
ItemData output = getBedrockItemFromIdentifierJson(outputEntry, outputNode);
UUID uuid = UUID.randomUUID();
if (type == 1) {
// Shaped recipe
List<String> shape = new ArrayList<>();
// Get the shape of the recipe
for (JsonNode chars : node.get("shape")) {
shape.add(chars.asText());
}
// In recipes.json each recipe is mapped by a letter
Map<String, ItemData> letterToRecipe = new HashMap<>();
Iterator<Map.Entry<String, JsonNode>> iterator = node.get("inputs").fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
JsonNode inputNode = entry.getValue();
ItemMapping inputEntry = mappings.getMapping(inputNode.get("identifier").asText());
letterToRecipe.put(entry.getKey(), getBedrockItemFromIdentifierJson(inputEntry, inputNode));
}
List<ItemData> inputs = new ArrayList<>(shape.size() * shape.get(0).length());
int i = 0;
// Create a linear array of items from the "cube" of the shape
for (int j = 0; i < shape.size() * shape.get(0).length(); j++) {
for (char c : shape.get(j).toCharArray()) {
ItemData data = letterToRecipe.getOrDefault(String.valueOf(c), ItemData.AIR);
inputs.add(data);
i++;
}
}
/* Convert into a Java recipe class for autocrafting */
List<Ingredient> ingredients = new ArrayList<>();
for (ItemData input : inputs) {
ingredients.add(new Ingredient(new ItemStack[] { ItemTranslator.translateToJava(input, mappings) }));
}
GeyserRecipe recipe = new GeyserShapedRecipe(shape.get(0).length(), shape.size(), ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
recipes.put(netId, recipe);
return CraftingData.fromShaped(uuid.toString(), shape.get(0).length(), shape.size(), inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId);
}
List<ItemData> inputs = new ObjectArrayList<>();
for (JsonNode entry : node.get("inputs")) {
ItemMapping inputEntry = mappings.getMapping(entry.get("identifier").asText());
inputs.add(getBedrockItemFromIdentifierJson(inputEntry, entry));
}
/* Convert into a Java Recipe class for autocrafting */
List<Ingredient> ingredients = new ArrayList<>();
for (ItemData input : inputs) {
ingredients.add(new Ingredient(new ItemStack[] { ItemTranslator.translateToJava(input, mappings) }));
}
GeyserRecipe recipe = new GeyserShapelessRecipe(ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
recipes.put(netId, recipe);
if (type == 5) {
// Shulker box
return CraftingData.fromShulkerBox(uuid.toString(), inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId);
}
return CraftingData.fromShapeless(uuid.toString(), inputs, Collections.singletonList(output), uuid, "crafting_table", 0, netId);
}
Aggregations