Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-20 15:00:11 +01:00
Store recipes in a more compact GeyserRecipe type
This prevents us from storing some unnecessary data. Also removes some 1.11 recipe compatibility code that is essentially unusable.
Dieser Commit ist enthalten in:
Ursprung
252348ebd8
Commit
811ae178c9
@ -32,27 +32,26 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.Constants;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserBootstrap;
|
||||||
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
||||||
import org.geysermc.geyser.command.CommandManager;
|
import org.geysermc.geyser.command.CommandManager;
|
||||||
import org.geysermc.geyser.session.auth.AuthType;
|
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
|
||||||
import org.geysermc.geyser.level.WorldManager;
|
import org.geysermc.geyser.level.WorldManager;
|
||||||
|
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||||
import org.geysermc.geyser.Constants;
|
|
||||||
import org.geysermc.geyser.util.FileUtils;
|
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
|
||||||
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
|
||||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor;
|
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor;
|
||||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager;
|
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager;
|
||||||
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSender;
|
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSender;
|
||||||
import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener;
|
import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener;
|
||||||
import org.geysermc.geyser.platform.spigot.world.GeyserSpigot1_11CraftingListener;
|
|
||||||
import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener;
|
import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener;
|
||||||
import org.geysermc.geyser.platform.spigot.world.manager.*;
|
import org.geysermc.geyser.platform.spigot.world.manager.*;
|
||||||
|
import org.geysermc.geyser.session.auth.AuthType;
|
||||||
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
import org.geysermc.geyser.util.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -235,11 +234,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
|
|
||||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
|
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this);
|
||||||
|
|
||||||
if (isPre1_12) {
|
|
||||||
// Register events needed to send all recipes to the client
|
|
||||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigot1_11CraftingListener(geyser), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(geyser));
|
this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(geyser));
|
||||||
|
|
||||||
// Check to ensure the current setup can support the protocol version Geyser uses
|
// Check to ensure the current setup can support the protocol version Geyser uses
|
||||||
|
@ -1,203 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* @author GeyserMC
|
|
||||||
* @link https://github.com/GeyserMC/Geyser
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.geysermc.geyser.platform.spigot.world;
|
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
|
|
||||||
import com.viaversion.viaversion.api.Via;
|
|
||||||
import com.viaversion.viaversion.api.data.MappingData;
|
|
||||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
|
||||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
|
||||||
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
|
|
||||||
import com.viaversion.viaversion.util.Pair;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.inventory.Recipe;
|
|
||||||
import org.bukkit.inventory.ShapedRecipe;
|
|
||||||
import org.bukkit.inventory.ShapelessRecipe;
|
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
|
||||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
|
||||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
|
||||||
import org.geysermc.geyser.util.InventoryUtils;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to send all available recipes from the server to the client, as a valid recipe book packet won't be sent by the server.
|
|
||||||
* Requires ViaVersion.
|
|
||||||
*/
|
|
||||||
public class GeyserSpigot1_11CraftingListener implements Listener {
|
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
|
||||||
/**
|
|
||||||
* Specific mapping data for 1.12 to 1.13. Used to convert the 1.12 item into 1.13.
|
|
||||||
*/
|
|
||||||
private final MappingData mappingData1_12to1_13;
|
|
||||||
/**
|
|
||||||
* The list of all protocols from the client's version to 1.13.
|
|
||||||
*/
|
|
||||||
private final List<ProtocolPathEntry> protocolList;
|
|
||||||
|
|
||||||
public GeyserSpigot1_11CraftingListener(GeyserImpl geyser) {
|
|
||||||
this.geyser = geyser;
|
|
||||||
this.mappingData1_12to1_13 = Via.getManager().getProtocolManager().getProtocol(Protocol1_13To1_12_2.class).getMappingData();
|
|
||||||
this.protocolList = Via.getManager().getProtocolManager().getProtocolPath(MinecraftProtocol.getJavaProtocolVersion(),
|
|
||||||
ProtocolVersion.v1_13.getVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
GeyserSession session = null;
|
|
||||||
for (GeyserSession otherSession : geyser.getSessionManager().getSessions().values()) {
|
|
||||||
if (otherSession.name().equals(event.getPlayer().getName())) {
|
|
||||||
session = otherSession;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (session == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendServerRecipes(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendServerRecipes(GeyserSession session) {
|
|
||||||
int netId = InventoryUtils.LAST_RECIPE_NET_ID;
|
|
||||||
|
|
||||||
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
|
||||||
craftingDataPacket.setCleanRecipes(true);
|
|
||||||
|
|
||||||
Iterator<Recipe> recipeIterator = Bukkit.getServer().recipeIterator();
|
|
||||||
while (recipeIterator.hasNext()) {
|
|
||||||
Recipe recipe = recipeIterator.next();
|
|
||||||
|
|
||||||
Pair<ItemStack, ItemData> outputs = translateToBedrock(session, recipe.getResult());
|
|
||||||
ItemStack javaOutput = outputs.getKey();
|
|
||||||
ItemData output = outputs.getValue();
|
|
||||||
if (output == null || output.getId() == 0) continue; // If items make air we don't want that
|
|
||||||
|
|
||||||
boolean isNotAllAir = false; // Check for all-air recipes
|
|
||||||
if (recipe instanceof ShapedRecipe shapedRecipe) {
|
|
||||||
int size = shapedRecipe.getShape().length * shapedRecipe.getShape()[0].length();
|
|
||||||
Ingredient[] ingredients = new Ingredient[size];
|
|
||||||
ItemData[] input = new ItemData[size];
|
|
||||||
for (int i = 0; i < input.length; i++) {
|
|
||||||
// Index is converting char to integer, adding i then converting back to char based on ASCII code
|
|
||||||
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapedRecipe.getIngredientMap().get((char) ('a' + i)));
|
|
||||||
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
|
|
||||||
input[i] = result.getValue();
|
|
||||||
isNotAllAir |= input[i].getId() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNotAllAir) continue;
|
|
||||||
UUID uuid = UUID.randomUUID();
|
|
||||||
// Add recipe to our internal cache
|
|
||||||
ShapedRecipeData data = new ShapedRecipeData(shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length,
|
|
||||||
"", ingredients, javaOutput);
|
|
||||||
session.getCraftingRecipes().put(netId,
|
|
||||||
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPED, uuid.toString(), data));
|
|
||||||
|
|
||||||
// Add recipe for Bedrock
|
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
|
||||||
shapedRecipe.getShape()[0].length(), shapedRecipe.getShape().length, Arrays.asList(input),
|
|
||||||
Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
|
|
||||||
} else if (recipe instanceof ShapelessRecipe shapelessRecipe) {
|
|
||||||
Ingredient[] ingredients = new Ingredient[shapelessRecipe.getIngredientList().size()];
|
|
||||||
ItemData[] input = new ItemData[shapelessRecipe.getIngredientList().size()];
|
|
||||||
|
|
||||||
for (int i = 0; i < input.length; i++) {
|
|
||||||
Pair<ItemStack, ItemData> result = translateToBedrock(session, shapelessRecipe.getIngredientList().get(i));
|
|
||||||
ingredients[i] = new Ingredient(new ItemStack[]{result.getKey()});
|
|
||||||
input[i] = result.getValue();
|
|
||||||
isNotAllAir |= input[i].getId() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNotAllAir) continue;
|
|
||||||
UUID uuid = UUID.randomUUID();
|
|
||||||
// Add recipe to our internal cache
|
|
||||||
ShapelessRecipeData data = new ShapelessRecipeData("", ingredients, javaOutput);
|
|
||||||
session.getCraftingRecipes().put(netId,
|
|
||||||
new com.github.steveice10.mc.protocol.data.game.recipe.Recipe(RecipeType.CRAFTING_SHAPELESS, uuid.toString(), data));
|
|
||||||
|
|
||||||
// Add recipe for Bedrock
|
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
|
||||||
Arrays.asList(input), Collections.singletonList(output), uuid, "crafting_table", 0, netId++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
session.sendUpstreamPacket(craftingDataPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private Pair<ItemStack, ItemData> translateToBedrock(GeyserSession session, org.bukkit.inventory.ItemStack itemStack) {
|
|
||||||
if (itemStack != null && itemStack.getData() != null) {
|
|
||||||
if (itemStack.getType().getId() == 0) {
|
|
||||||
return new Pair<>(null, ItemData.AIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
int legacyId = (itemStack.getType().getId() << 4) | (itemStack.getData().getData() & 0xFFFF);
|
|
||||||
|
|
||||||
if (itemStack.getType().getId() == 355 && itemStack.getData().getData() == (byte) 0) { // Handle bed color since the server will always be pre-1.12
|
|
||||||
legacyId = (itemStack.getType().getId() << 4) | ((byte) 14 & 0xFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 and so on
|
|
||||||
int itemId;
|
|
||||||
if (mappingData1_12to1_13.getItemMappings().containsKey(legacyId)) {
|
|
||||||
itemId = mappingData1_12to1_13.getNewItemId(legacyId);
|
|
||||||
} else if (mappingData1_12to1_13.getItemMappings().containsKey((itemStack.getType().getId() << 4) | (0))) {
|
|
||||||
itemId = mappingData1_12to1_13.getNewItemId((itemStack.getType().getId() << 4) | (0));
|
|
||||||
} else {
|
|
||||||
// No ID found, just send back air
|
|
||||||
return new Pair<>(null, ItemData.AIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = protocolList.size() - 1; i >= 0; i--) {
|
|
||||||
MappingData mappingData = protocolList.get(i).getProtocol().getMappingData();
|
|
||||||
if (mappingData != null) {
|
|
||||||
itemId = mappingData.getNewItemId(itemId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack mcItemStack = new ItemStack(itemId, itemStack.getAmount());
|
|
||||||
ItemData finalData = ItemTranslator.translateToBedrock(session, mcItemStack);
|
|
||||||
return new Pair<>(mcItemStack, finalData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty slot, most likely
|
|
||||||
return new Pair<>(null, ItemData.AIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A more compact version of {@link com.github.steveice10.mc.protocol.data.game.recipe.Recipe}.
|
||||||
|
*/
|
||||||
|
public interface GeyserRecipe {
|
||||||
|
/**
|
||||||
|
* Whether the recipe is flexible or not in which items can be placed where.
|
||||||
|
*/
|
||||||
|
boolean isShaped();
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
||||||
|
|
||||||
|
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, ItemStack result) implements GeyserRecipe {
|
||||||
|
|
||||||
|
public GeyserShapedRecipe(ShapedRecipeData data) {
|
||||||
|
this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShaped() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.inventory.recipe;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
||||||
|
|
||||||
|
public record GeyserShapelessRecipe(Ingredient[] ingredients, ItemStack result) implements GeyserRecipe {
|
||||||
|
|
||||||
|
public GeyserShapelessRecipe(ShapelessRecipeData data) {
|
||||||
|
this(data.getIngredients(), data.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShaped() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import org.geysermc.geyser.entity.EntityDefinition;
|
import org.geysermc.geyser.entity.EntityDefinition;
|
||||||
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
|
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||||
import org.geysermc.geyser.registry.loader.*;
|
import org.geysermc.geyser.registry.loader.*;
|
||||||
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
|
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
|
||||||
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
|
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
|
||||||
@ -141,7 +142,7 @@ public final class Registries {
|
|||||||
/**
|
/**
|
||||||
* A versioned registry holding all the recipes, with the net ID being the key, and {@link Recipe} as the value.
|
* A versioned registry holding all the recipes, with the net ID being the key, and {@link Recipe} as the value.
|
||||||
*/
|
*/
|
||||||
public static final VersionedRegistry<Int2ObjectMap<Recipe>> RECIPES = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
|
public static final VersionedRegistry<Int2ObjectMap<GeyserRecipe>> RECIPES = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapped registry holding the available records, with the ID of the record being the key, and the {@link com.nukkitx.protocol.bedrock.data.SoundEvent}
|
* A mapped registry holding the available records, with the ID of the record being the key, and the {@link com.nukkitx.protocol.bedrock.data.SoundEvent}
|
||||||
|
@ -28,10 +28,7 @@ package org.geysermc.geyser.registry.populator;
|
|||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtUtils;
|
import com.nukkitx.nbt.NbtUtils;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
||||||
@ -40,6 +37,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
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.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||||
@ -71,7 +71,7 @@ public class RecipeRegistryPopulator {
|
|||||||
// Make a bit of an assumption here that the last recipe net ID will be equivalent between all versions
|
// Make a bit of an assumption here that the last recipe net ID will be equivalent between all versions
|
||||||
LAST_RECIPE_NET_ID = currentRecipeId;
|
LAST_RECIPE_NET_ID = currentRecipeId;
|
||||||
Map<RecipeType, List<CraftingData>> craftingData = new EnumMap<>(RecipeType.class);
|
Map<RecipeType, List<CraftingData>> craftingData = new EnumMap<>(RecipeType.class);
|
||||||
Int2ObjectMap<Recipe> recipes = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<GeyserRecipe> recipes = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
craftingData.put(RecipeType.CRAFTING_SPECIAL_BOOKCLONING,
|
craftingData.put(RecipeType.CRAFTING_SPECIAL_BOOKCLONING,
|
||||||
Collections.singletonList(CraftingData.fromMulti(UUID.fromString("d1ca6b84-338e-4f2f-9c6b-76cc8b4bd98d"), ++LAST_RECIPE_NET_ID)));
|
Collections.singletonList(CraftingData.fromMulti(UUID.fromString("d1ca6b84-338e-4f2f-9c6b-76cc8b4bd98d"), ++LAST_RECIPE_NET_ID)));
|
||||||
@ -124,7 +124,7 @@ public class RecipeRegistryPopulator {
|
|||||||
* @param recipes a list of all the recipes
|
* @param recipes a list of all the recipes
|
||||||
* @return the {@link CraftingData} to send to the Bedrock client.
|
* @return the {@link CraftingData} to send to the Bedrock client.
|
||||||
*/
|
*/
|
||||||
private static CraftingData getCraftingDataFromJsonNode(JsonNode node, Int2ObjectMap<Recipe> recipes, ItemMappings mappings) {
|
private static CraftingData getCraftingDataFromJsonNode(JsonNode node, Int2ObjectMap<GeyserRecipe> recipes, ItemMappings mappings) {
|
||||||
int netId = ++LAST_RECIPE_NET_ID;
|
int netId = ++LAST_RECIPE_NET_ID;
|
||||||
int type = node.get("bedrockRecipeType").asInt();
|
int type = node.get("bedrockRecipeType").asInt();
|
||||||
JsonNode outputNode = node.get("output");
|
JsonNode outputNode = node.get("output");
|
||||||
@ -165,9 +165,8 @@ public class RecipeRegistryPopulator {
|
|||||||
for (ItemData input : inputs) {
|
for (ItemData input : inputs) {
|
||||||
ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)}));
|
ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)}));
|
||||||
}
|
}
|
||||||
ShapedRecipeData data = new ShapedRecipeData(shape.get(0).length(), shape.size(), "crafting_table",
|
GeyserRecipe recipe = new GeyserShapedRecipe(shape.get(0).length(), shape.size(),
|
||||||
ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
|
ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
|
||||||
Recipe recipe = new Recipe(RecipeType.CRAFTING_SHAPED, "", data);
|
|
||||||
recipes.put(netId, recipe);
|
recipes.put(netId, recipe);
|
||||||
/* Convert end */
|
/* Convert end */
|
||||||
|
|
||||||
@ -185,9 +184,7 @@ public class RecipeRegistryPopulator {
|
|||||||
for (ItemData input : inputs) {
|
for (ItemData input : inputs) {
|
||||||
ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)}));
|
ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)}));
|
||||||
}
|
}
|
||||||
ShapelessRecipeData data = new ShapelessRecipeData("crafting_table",
|
GeyserRecipe recipe = new GeyserShapelessRecipe(ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
|
||||||
ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings));
|
|
||||||
Recipe recipe = new Recipe(RecipeType.CRAFTING_SHAPELESS, "", data);
|
|
||||||
recipes.put(netId, recipe);
|
recipes.put(netId, recipe);
|
||||||
/* Convert end */
|
/* Convert end */
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException;
|
|||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.HandPreference;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.HandPreference;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility;
|
import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility;
|
||||||
import com.github.steveice10.mc.protocol.data.game.setting.SkinPart;
|
import com.github.steveice10.mc.protocol.data.game.setting.SkinPart;
|
||||||
import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic;
|
import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic;
|
||||||
@ -94,6 +93,7 @@ import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
|||||||
import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
|
import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
|
||||||
import org.geysermc.geyser.inventory.Inventory;
|
import org.geysermc.geyser.inventory.Inventory;
|
||||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||||
import org.geysermc.geyser.level.WorldManager;
|
import org.geysermc.geyser.level.WorldManager;
|
||||||
import org.geysermc.geyser.level.physics.CollisionManager;
|
import org.geysermc.geyser.level.physics.CollisionManager;
|
||||||
import org.geysermc.geyser.network.netty.LocalSession;
|
import org.geysermc.geyser.network.netty.LocalSession;
|
||||||
@ -350,7 +350,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||||||
private Entity mouseoverEntity;
|
private Entity mouseoverEntity;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private Int2ObjectMap<Recipe> craftingRecipes;
|
private Int2ObjectMap<GeyserRecipe> craftingRecipes;
|
||||||
private final Set<String> unlockedRecipes;
|
private final Set<String> unlockedRecipes;
|
||||||
private final AtomicInteger lastRecipeNetId;
|
private final AtomicInteger lastRecipeNetId;
|
||||||
|
|
||||||
|
@ -28,9 +28,6 @@ package org.geysermc.geyser.translator.inventory;
|
|||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
|
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
|
||||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||||
@ -45,6 +42,9 @@ import org.geysermc.geyser.GeyserImpl;
|
|||||||
import org.geysermc.geyser.inventory.*;
|
import org.geysermc.geyser.inventory.*;
|
||||||
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.GeyserShapedRecipe;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.inventory.chest.SingleChestInventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.chest.SingleChestInventoryTranslator;
|
||||||
@ -535,7 +535,6 @@ public abstract class InventoryTranslator {
|
|||||||
}
|
}
|
||||||
int gridDimensions = gridSize == 4 ? 2 : 3;
|
int gridDimensions = gridSize == 4 ? 2 : 3;
|
||||||
|
|
||||||
Recipe recipe;
|
|
||||||
Ingredient[] ingredients = new Ingredient[0];
|
Ingredient[] ingredients = new Ingredient[0];
|
||||||
ItemStack output = null;
|
ItemStack output = null;
|
||||||
int recipeWidth = 0;
|
int recipeWidth = 0;
|
||||||
@ -564,7 +563,7 @@ public abstract class InventoryTranslator {
|
|||||||
craftState = CraftState.RECIPE_ID;
|
craftState = CraftState.RECIPE_ID;
|
||||||
|
|
||||||
int recipeId = autoCraftAction.getRecipeNetworkId();
|
int recipeId = autoCraftAction.getRecipeNetworkId();
|
||||||
recipe = session.getCraftingRecipes().get(recipeId);
|
GeyserRecipe recipe = session.getCraftingRecipes().get(recipeId);
|
||||||
if (recipe == null) {
|
if (recipe == null) {
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
@ -578,26 +577,23 @@ public abstract class InventoryTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (recipe.getType()) {
|
if (recipe.isShaped()) {
|
||||||
case CRAFTING_SHAPED -> {
|
GeyserShapedRecipe shapedRecipe = (GeyserShapedRecipe) recipe;
|
||||||
ShapedRecipeData shapedData = (ShapedRecipeData) recipe.getData();
|
ingredients = shapedRecipe.ingredients();
|
||||||
ingredients = shapedData.getIngredients();
|
recipeWidth = shapedRecipe.width();
|
||||||
recipeWidth = shapedData.getWidth();
|
output = shapedRecipe.result();
|
||||||
output = shapedData.getResult();
|
if (recipeWidth > gridDimensions || shapedRecipe.height() > gridDimensions) {
|
||||||
if (shapedData.getWidth() > gridDimensions || shapedData.getHeight() > gridDimensions) {
|
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
case CRAFTING_SHAPELESS -> {
|
GeyserShapelessRecipe shapelessRecipe = (GeyserShapelessRecipe) recipe;
|
||||||
ShapelessRecipeData shapelessData = (ShapelessRecipeData) recipe.getData();
|
ingredients = shapelessRecipe.ingredients();
|
||||||
ingredients = shapelessData.getIngredients();
|
|
||||||
recipeWidth = gridDimensions;
|
recipeWidth = gridDimensions;
|
||||||
output = shapelessData.getResult();
|
output = shapelessRecipe.result();
|
||||||
if (ingredients.length > gridSize) {
|
if (ingredients.length > gridSize) {
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CRAFT_RESULTS_DEPRECATED: {
|
case CRAFT_RESULTS_DEPRECATED: {
|
||||||
|
@ -42,6 +42,9 @@ import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
|||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
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.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
@ -80,7 +83,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
|
|
||||||
boolean applySmithingRecipes = session.getUpstream().getProtocolVersion() >= Bedrock_v486.V486_CODEC.getProtocolVersion();
|
boolean applySmithingRecipes = session.getUpstream().getProtocolVersion() >= Bedrock_v486.V486_CODEC.getProtocolVersion();
|
||||||
|
|
||||||
Int2ObjectMap<Recipe> recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion()));
|
Int2ObjectMap<GeyserRecipe> recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion()));
|
||||||
Int2ObjectMap<List<StoneCuttingRecipeData>> unsortedStonecutterData = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<List<StoneCuttingRecipeData>> unsortedStonecutterData = new Int2ObjectOpenHashMap<>();
|
||||||
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
||||||
craftingDataPacket.setCleanRecipes(true);
|
craftingDataPacket.setCleanRecipes(true);
|
||||||
@ -100,7 +103,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
||||||
Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId));
|
Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId));
|
||||||
recipeMap.put(netId++, recipe);
|
recipeMap.put(netId++, new GeyserShapelessRecipe(shapelessRecipeData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case CRAFTING_SHAPED -> {
|
case CRAFTING_SHAPED -> {
|
||||||
@ -118,7 +121,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
||||||
shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), Arrays.asList(inputs),
|
shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), Arrays.asList(inputs),
|
||||||
Collections.singletonList(output), uuid, "crafting_table", 0, netId));
|
Collections.singletonList(output), uuid, "crafting_table", 0, netId));
|
||||||
recipeMap.put(netId++, recipe);
|
recipeMap.put(netId++, new GeyserShapedRecipe(shapedRecipeData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case STONECUTTING -> {
|
case STONECUTTING -> {
|
||||||
|
@ -27,9 +27,6 @@ package org.geysermc.geyser.translator.protocol.java.inventory;
|
|||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
||||||
@ -38,6 +35,7 @@ import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
|
|||||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||||
import org.geysermc.geyser.inventory.Inventory;
|
import org.geysermc.geyser.inventory.Inventory;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
|
||||||
@ -165,9 +163,8 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapedRecipeData data = new ShapedRecipeData(width, height, "", javaIngredients, item);
|
|
||||||
// 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 Recipe(RecipeType.CRAFTING_SHAPED, uuid.toString(), data));
|
session.getCraftingRecipes().put(newRecipeId, new GeyserShapedRecipe(width, height, javaIngredients, item));
|
||||||
|
|
||||||
CraftingDataPacket craftPacket = new CraftingDataPacket();
|
CraftingDataPacket craftPacket = new CraftingDataPacket();
|
||||||
craftPacket.getCraftingData().add(CraftingData.fromShaped(
|
craftPacket.getCraftingData().add(CraftingData.fromShaped(
|
||||||
|
@ -28,10 +28,6 @@ package org.geysermc.geyser.util;
|
|||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
@ -47,14 +43,17 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
|
|||||||
import org.geysermc.geyser.inventory.Inventory;
|
import org.geysermc.geyser.inventory.Inventory;
|
||||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||||
import org.geysermc.geyser.inventory.click.Click;
|
import org.geysermc.geyser.inventory.click.Click;
|
||||||
|
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.registry.Registries;
|
||||||
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
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;
|
||||||
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator;
|
||||||
import org.geysermc.geyser.registry.Registries;
|
|
||||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -361,7 +360,7 @@ public class InventoryUtils {
|
|||||||
* @param output if not null, the recipe has to output this item
|
* @param output if not null, the recipe has to output this item
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Recipe getValidRecipe(final GeyserSession session, final @Nullable ItemStack output, final IntFunction<GeyserItemStack> inventoryGetter,
|
public static GeyserRecipe getValidRecipe(final GeyserSession session, final @Nullable ItemStack output, 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 nonAirCount = 0; // Used for shapeless recipes for amount of items needed in recipe
|
int nonAirCount = 0; // Used for shapeless recipes for amount of items needed in recipe
|
||||||
for (int row = firstRow; row < height + firstRow; row++) {
|
for (int row = firstRow; row < height + firstRow; row++) {
|
||||||
@ -373,14 +372,14 @@ public class InventoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recipes:
|
recipes:
|
||||||
for (Recipe recipe : session.getCraftingRecipes().values()) {
|
for (GeyserRecipe recipe : session.getCraftingRecipes().values()) {
|
||||||
if (recipe.getType() == RecipeType.CRAFTING_SHAPED) {
|
if (recipe.isShaped()) {
|
||||||
ShapedRecipeData data = (ShapedRecipeData) recipe.getData();
|
GeyserShapedRecipe shapedRecipe = (GeyserShapedRecipe) recipe;
|
||||||
if (output != null && !data.getResult().equals(output)) {
|
if (output != null && !shapedRecipe.result().equals(output)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ingredient[] ingredients = data.getIngredients();
|
Ingredient[] ingredients = shapedRecipe.ingredients();
|
||||||
if (data.getWidth() != width || data.getHeight() != height || width * height != ingredients.length) {
|
if (shapedRecipe.width() != width || shapedRecipe.height() != height || width * height != ingredients.length) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,18 +396,17 @@ public class InventoryUtils {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return recipe;
|
} else {
|
||||||
} else if (recipe.getType() == RecipeType.CRAFTING_SHAPELESS) {
|
GeyserShapelessRecipe data = (GeyserShapelessRecipe) recipe;
|
||||||
ShapelessRecipeData data = (ShapelessRecipeData) recipe.getData();
|
if (output != null && !data.result().equals(output)) {
|
||||||
if (output != null && !data.getResult().equals(output)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (nonAirCount != data.getIngredients().length) {
|
if (nonAirCount != data.ingredients().length) {
|
||||||
// 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.getIngredients().length; i++) {
|
for (int i = 0; i < data.ingredients().length; i++) {
|
||||||
Ingredient ingredient = data.getIngredients()[i];
|
Ingredient ingredient = data.ingredients()[i];
|
||||||
for (ItemStack itemStack : ingredient.getOptions()) {
|
for (ItemStack itemStack : ingredient.getOptions()) {
|
||||||
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
|
||||||
@ -432,8 +430,8 @@ public class InventoryUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return recipe;
|
|
||||||
}
|
}
|
||||||
|
return recipe;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren