Update adapters to support 1.19.3 and add biome command completions

This commit is contained in:
Camotoy 2022-12-13 13:53:28 -05:00
parent 6876a90c3b
commit 7c26036906
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
6 changed files with 98 additions and 22 deletions

View File

@ -32,6 +32,7 @@ import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter; import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Nullable;
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
protected final SpigotWorldAdapter adapter; protected final SpigotWorldAdapter adapter;
@ -49,4 +50,12 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
} }
return adapter.getBlockAt(player.getWorld(), x, y, z); return adapter.getBlockAt(player.getWorld(), x, y, z);
} }
@Nullable
@Override
public String[] getBiomeIdentifiers(boolean withTags) {
// Biome identifiers will basically always be the same for one server, since you have to re-send the
// ClientboundLoginPacket to change the registry. Therefore, don't bother caching for each player.
return adapter.getBiomeSuggestions(withTags);
}
} }

View File

@ -31,6 +31,7 @@ import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMap;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nullable;
import java.util.Locale; import java.util.Locale;
/** /**
@ -157,4 +158,12 @@ public abstract class WorldManager {
* @return True if the player has the requested permission, false if not * @return True if the player has the requested permission, false if not
*/ */
public abstract boolean hasPermission(GeyserSession session, String permission); public abstract boolean hasPermission(GeyserSession session, String permission);
/**
* Returns a list of biome identifiers available on the server.
*/
@Nullable
public String[] getBiomeIdentifiers(boolean withTags) {
return null;
}
} }

View File

@ -296,6 +296,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*/ */
@Setter @Setter
private String worldName = null; private String worldName = null;
/**
* As of Java 1.19.3, the client only uses these for commands.
*/
@Setter
private String[] levels;
private boolean sneaking; private boolean sneaking;

View File

@ -44,6 +44,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.event.downstream.ServerDefineCommandsEvent; import org.geysermc.geyser.api.event.downstream.ServerDefineCommandsEvent;
import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.command.GeyserCommandManager;
@ -198,7 +199,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
if (commandNode.getChildIndices().length >= 1) { if (commandNode.getChildIndices().length >= 1) {
// Create the root param node and build all the children // Create the root param node and build all the children
ParamInfo rootParam = new ParamInfo(commandNode, null); ParamInfo rootParam = new ParamInfo(commandNode, null);
rootParam.buildChildren(session, allNodes); rootParam.buildChildren(new CommandBuilderContext(session), allNodes);
List<CommandParamData[]> treeData = rootParam.getTree(); List<CommandParamData[]> treeData = rootParam.getTree();
@ -211,11 +212,11 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
/** /**
* Convert Java edition command types to Bedrock edition * Convert Java edition command types to Bedrock edition
* *
* @param session the session * @param context the session's command context
* @param node Command type to convert * @param node Command type to convert
* @return Bedrock parameter data type * @return Bedrock parameter data type
*/ */
private static Object mapCommandType(GeyserSession session, CommandNode node) { private static Object mapCommandType(CommandBuilderContext context, CommandNode node) {
CommandParser parser = node.getParser(); CommandParser parser = node.getParser();
if (parser == null) { if (parser == null) {
return CommandParam.STRING; return CommandParam.STRING;
@ -232,21 +233,24 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
case RESOURCE_LOCATION, FUNCTION -> CommandParam.FILE_PATH; case RESOURCE_LOCATION, FUNCTION -> CommandParam.FILE_PATH;
case BOOL -> ENUM_BOOLEAN; case BOOL -> ENUM_BOOLEAN;
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
case BLOCK_STATE -> BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.get().keySet().toArray(new String[0]); case BLOCK_STATE -> context.getBlockStates();
case ITEM_STACK -> session.getItemMappings().getItemNames(); case ITEM_STACK -> context.session.getItemMappings().getItemNames();
case COLOR -> VALID_COLORS; case COLOR -> VALID_COLORS;
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS; case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
case RESOURCE, RESOURCE_OR_TAG -> { case RESOURCE -> handleResource(context, ((ResourceProperties) node.getProperties()).getRegistryKey(), false);
String resource = ((ResourceProperties) node.getProperties()).getRegistryKey(); case RESOURCE_OR_TAG -> handleResource(context, ((ResourceProperties) node.getProperties()).getRegistryKey(), true);
yield switch (resource) { case DIMENSION -> context.session.getLevels();
// minecraft:worldgen/biome is also valid but we currently don't cache biome IDs default -> CommandParam.STRING;
case "minecraft:attribute" -> ATTRIBUTES; };
case "minecraft:enchantment" -> Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS; }
case "minecraft:entity_type" -> Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]);
case "minecraft:mob_effect" -> ALL_EFFECT_IDENTIFIERS; private static Object handleResource(CommandBuilderContext context, String resource, boolean tags) {
default -> CommandParam.STRING; return switch (resource) {
}; case "minecraft:attribute" -> ATTRIBUTES;
} case "minecraft:enchantment" -> Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS;
case "minecraft:entity_type" -> context.getEntityTypes();
case "minecraft:mob_effect" -> ALL_EFFECT_IDENTIFIERS;
case "minecraft:worldgen/biome" -> tags ? context.getBiomesWithTags() : context.getBiomes();
default -> CommandParam.STRING; default -> CommandParam.STRING;
}; };
} }
@ -254,7 +258,55 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
/** /**
* Stores the command description and parameter data for best optimizing the Bedrock commands packet. * Stores the command description and parameter data for best optimizing the Bedrock commands packet.
*/ */
private static record BedrockCommandInfo(String name, String description, CommandParamData[][] paramData) implements ServerDefineCommandsEvent.CommandInfo { private record BedrockCommandInfo(String name, String description, CommandParamData[][] paramData) implements ServerDefineCommandsEvent.CommandInfo {
}
/**
* Stores command completions so we don't have to rebuild the same values multiple times.
*/
@MonotonicNonNull
private static class CommandBuilderContext {
private final GeyserSession session;
private Object biomesWithTags;
private Object biomesNoTags;
private String[] blockStates;
private String[] entityTypes;
CommandBuilderContext(GeyserSession session) {
this.session = session;
}
private Object getBiomes() {
if (biomesNoTags != null) {
return biomesNoTags;
}
String[] identifiers = session.getGeyser().getWorldManager().getBiomeIdentifiers(false);
return (biomesNoTags = identifiers != null ? identifiers : CommandParam.STRING);
}
private Object getBiomesWithTags() {
if (biomesWithTags != null) {
return biomesWithTags;
}
String[] identifiers = session.getGeyser().getWorldManager().getBiomeIdentifiers(true);
return (biomesWithTags = identifiers != null ? identifiers : CommandParam.STRING);
}
private String[] getBlockStates() {
if (blockStates != null) {
return blockStates;
}
return (blockStates = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.get().keySet().toArray(new String[0]));
}
private String[] getEntityTypes() {
if (entityTypes != null) {
return entityTypes;
}
return (entityTypes = Registries.JAVA_ENTITY_IDENTIFIERS.get().keySet().toArray(new String[0]));
}
} }
@Getter @Getter
@ -279,10 +331,10 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
/** /**
* Build the array of all the child parameters (recursive) * Build the array of all the child parameters (recursive)
* *
* @param session the session * @param context the session's command builder context
* @param allNodes Every command node * @param allNodes Every command node
*/ */
public void buildChildren(GeyserSession session, CommandNode[] allNodes) { public void buildChildren(CommandBuilderContext context, CommandNode[] allNodes) {
for (int paramID : paramNode.getChildIndices()) { for (int paramID : paramNode.getChildIndices()) {
CommandNode paramNode = allNodes[paramID]; CommandNode paramNode = allNodes[paramID];
@ -320,7 +372,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
} }
} else { } else {
// Put the non-enum param into the list // Put the non-enum param into the list
Object mappedType = mapCommandType(session, paramNode); Object mappedType = mapCommandType(context, paramNode);
CommandEnumData enumData = null; CommandEnumData enumData = null;
CommandParam type = null; CommandParam type = null;
boolean optional = this.paramNode.isExecutable(); boolean optional = this.paramNode.isExecutable();
@ -343,7 +395,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
// Recursively build all child options // Recursively build all child options
for (ParamInfo child : children) { for (ParamInfo child : children) {
child.buildChildren(session, allNodes); child.buildChildren(context, allNodes);
} }
} }

View File

@ -87,6 +87,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
session.getWorldCache().removeScoreboard(); session.getWorldCache().removeScoreboard();
} }
session.setWorldName(packet.getWorldName()); session.setWorldName(packet.getWorldName());
session.setLevels(packet.getWorldNames());
BiomeTranslator.loadServerBiomes(session, packet.getRegistry()); BiomeTranslator.loadServerBiomes(session, packet.getRegistry());
session.getTagCache().clear(); session.getTagCache().clear();

View File

@ -21,7 +21,7 @@ jline = "3.21.0"
terminalconsoleappender = "1.2.0" terminalconsoleappender = "1.2.0"
paper = "1.19-R0.1-SNAPSHOT" paper = "1.19-R0.1-SNAPSHOT"
viaversion = "4.0.0" viaversion = "4.0.0"
adapters = "1.5-SNAPSHOT" adapters = "1.6-SNAPSHOT"
commodore = "2.2" commodore = "2.2"
bungeecord = "a7c6ede" bungeecord = "a7c6ede"
velocity = "3.0.0" velocity = "3.0.0"