Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
Fix stonecutters for Bedrock 1.18.30
Also add an option in debug mode to not log pings in the event they're spammy.
Dieser Commit ist enthalten in:
Ursprung
b528a1c4f6
Commit
e923325246
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param buttonId the button that needs to be pressed for Java Edition to accept this item.
|
||||||
|
* @param output the expected output of this item when cut.
|
||||||
|
*/
|
||||||
|
public record GeyserStonecutterData(int buttonId, ItemStack output) {
|
||||||
|
}
|
@ -47,6 +47,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
||||||
|
private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client
|
The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client
|
||||||
*/
|
*/
|
||||||
@ -88,7 +90,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
|
public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) {
|
||||||
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", inetSocketAddress));
|
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", inetSocketAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ 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.inventory.recipe.GeyserRecipe;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
|
||||||
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;
|
||||||
@ -365,7 +366,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||||||
* The key is the Java ID of the item; the values are all the possible outputs' Java IDs sorted by their string identifier
|
* The key is the Java ID of the item; the values are all the possible outputs' Java IDs sorted by their string identifier
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
private Int2ObjectMap<IntList> stonecutterRecipes;
|
private Int2ObjectMap<GeyserStonecutterData> stonecutterRecipes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to work around 1.13's different behavior in villager trading menus.
|
* Whether to work around 1.13's different behavior in villager trading menus.
|
||||||
|
@ -144,7 +144,7 @@ public abstract class InventoryTranslator {
|
|||||||
/**
|
/**
|
||||||
* If {@link #shouldHandleRequestFirst(StackRequestActionData, Inventory)} returns true, this will be called
|
* If {@link #shouldHandleRequestFirst(StackRequestActionData, Inventory)} returns true, this will be called
|
||||||
*/
|
*/
|
||||||
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
protected ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,20 +31,14 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.Ser
|
|||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemStackRequest;
|
import com.nukkitx.protocol.bedrock.data.inventory.ItemStackRequest;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftResultsDeprecatedStackRequestActionData;
|
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData;
|
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType;
|
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType;
|
||||||
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import org.geysermc.geyser.inventory.*;
|
||||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
|
||||||
import org.geysermc.geyser.inventory.Inventory;
|
|
||||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
|
||||||
import org.geysermc.geyser.inventory.StonecutterContainer;
|
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
|
||||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
|
||||||
import org.geysermc.geyser.inventory.SlotType;
|
|
||||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
||||||
public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator {
|
public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||||
public StonecutterInventoryTranslator() {
|
public StonecutterInventoryTranslator() {
|
||||||
@ -53,31 +47,26 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) {
|
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) {
|
||||||
// First is pre-1.18. TODO remove after 1.17.40 support is dropped and refactor stonecutter support to use CraftRecipeStackRequestActionData's recipe ID
|
return action.getType() == StackRequestActionType.CRAFT_RECIPE;
|
||||||
return action.getType() == StackRequestActionType.CRAFT_NON_IMPLEMENTED_DEPRECATED || action.getType() == StackRequestActionType.CRAFT_RECIPE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
protected ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
||||||
// TODO: Also surely to change in the future
|
// Guarded by shouldHandleRequestFirst
|
||||||
StackRequestActionData data = request.getActions()[1];
|
CraftRecipeStackRequestActionData data = (CraftRecipeStackRequestActionData) request.getActions()[0];
|
||||||
if (!(data instanceof CraftResultsDeprecatedStackRequestActionData craftData)) {
|
|
||||||
|
// Look up all possible options of cutting from this ID
|
||||||
|
GeyserStonecutterData craftingData = session.getStonecutterRecipes().get(data.getRecipeNetworkId());
|
||||||
|
if (craftingData == null) {
|
||||||
return rejectRequest(request);
|
return rejectRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
StonecutterContainer container = (StonecutterContainer) inventory;
|
StonecutterContainer container = (StonecutterContainer) inventory;
|
||||||
// Get the ID of the item we are cutting
|
int button = craftingData.buttonId();
|
||||||
int id = inventory.getItem(0).getJavaId();
|
|
||||||
// Look up all possible options of cutting from this ID
|
|
||||||
IntList results = session.getStonecutterRecipes().get(id);
|
|
||||||
if (results == null) {
|
|
||||||
return rejectRequest(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack javaOutput = ItemTranslator.translateToJava(craftData.getResultItems()[0], session.getItemMappings());
|
|
||||||
int button = results.indexOf(javaOutput.getId());
|
|
||||||
// If we've already pressed the button with this item, no need to press it again!
|
// If we've already pressed the button with this item, no need to press it again!
|
||||||
if (container.getStonecutterButton() != button) {
|
if (container.getStonecutterButton() != button) {
|
||||||
|
ItemStack javaOutput = craftingData.output();
|
||||||
|
|
||||||
// Getting the index of the item in the Java stonecutter list
|
// Getting the index of the item in the Java stonecutter list
|
||||||
ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getId(), button);
|
ServerboundContainerButtonClickPacket packet = new ServerboundContainerButtonClickPacket(inventory.getId(), button);
|
||||||
session.sendDownstreamPacket(packet);
|
session.sendDownstreamPacket(packet);
|
||||||
|
@ -127,7 +127,7 @@ public class EnchantmentTranslator extends NbtItemStackTranslator {
|
|||||||
|
|
||||||
Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue());
|
Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue());
|
||||||
if (enchantment == null) {
|
if (enchantment == null) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Unknown java enchantment: " + javaEnchId.getValue());
|
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + javaEnchId.getValue());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
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.GeyserShapedRecipe;
|
||||||
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
||||||
|
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
|
||||||
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;
|
||||||
@ -167,7 +168,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
craftingDataPacket.getCraftingData().addAll(CARTOGRAPHY_RECIPES);
|
craftingDataPacket.getCraftingData().addAll(CARTOGRAPHY_RECIPES);
|
||||||
craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.get());
|
craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.get());
|
||||||
|
|
||||||
Int2ObjectMap<IntList> stonecutterRecipeMap = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<GeyserStonecutterData> stonecutterRecipeMap = new Int2ObjectOpenHashMap<>();
|
||||||
for (Int2ObjectMap.Entry<List<StoneCuttingRecipeData>> data : unsortedStonecutterData.int2ObjectEntrySet()) {
|
for (Int2ObjectMap.Entry<List<StoneCuttingRecipeData>> data : unsortedStonecutterData.int2ObjectEntrySet()) {
|
||||||
// Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
|
// Sort the list by each output item's Java identifier - this is how it's sorted on Java, and therefore
|
||||||
// We can get the correct order for button pressing
|
// We can get the correct order for button pressing
|
||||||
@ -176,11 +177,13 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
.getJavaIdentifier())));
|
.getJavaIdentifier())));
|
||||||
|
|
||||||
// Now that it's sorted, let's translate these recipes
|
// Now that it's sorted, let's translate these recipes
|
||||||
|
int buttonId = 0;
|
||||||
for (StoneCuttingRecipeData stoneCuttingData : data.getValue()) {
|
for (StoneCuttingRecipeData stoneCuttingData : data.getValue()) {
|
||||||
// As of 1.16.4, all stonecutter recipes have one ingredient option
|
// As of 1.16.4, all stonecutter recipes have one ingredient option
|
||||||
ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0];
|
ItemStack ingredient = stoneCuttingData.getIngredient().getOptions()[0];
|
||||||
ItemData input = ItemTranslator.translateToBedrock(session, ingredient);
|
ItemData input = ItemTranslator.translateToBedrock(session, ingredient);
|
||||||
ItemData output = ItemTranslator.translateToBedrock(session, stoneCuttingData.getResult());
|
ItemStack javaOutput = stoneCuttingData.getResult();
|
||||||
|
ItemData output = ItemTranslator.translateToBedrock(session, javaOutput);
|
||||||
if (input.equals(ItemData.AIR) || output.equals(ItemData.AIR)) {
|
if (input.equals(ItemData.AIR) || output.equals(ItemData.AIR)) {
|
||||||
// Probably modded items
|
// Probably modded items
|
||||||
continue;
|
continue;
|
||||||
@ -189,12 +192,11 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
|
|
||||||
// We need to register stonecutting recipes so they show up on Bedrock
|
// We need to register stonecutting recipes so they show up on Bedrock
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
||||||
Collections.singletonList(input), Collections.singletonList(output), uuid, "stonecutter", 0, netId++));
|
Collections.singletonList(input), Collections.singletonList(output), uuid, "stonecutter", 0, netId));
|
||||||
|
|
||||||
// Save the recipe list for reference when crafting
|
// Save the recipe list for reference when crafting
|
||||||
// Add the ingredient as the key and all possible values as the value
|
// Add the net ID as the key and the button required + output for the value
|
||||||
IntList outputs = stonecutterRecipeMap.computeIfAbsent(ingredient.getId(), ($) -> new IntArrayList());
|
stonecutterRecipeMap.put(netId++, new GeyserStonecutterData(buttonId++, javaOutput));
|
||||||
outputs.add(stoneCuttingData.getResult().getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren