feat: initial 1.21.5 with adventure still not being updated

This commit is contained in:
Chayapak 2025-04-20 08:57:58 +07:00
parent ac9c26bcd0
commit db56afd319
Signed by: ChomeNS
SSH key fingerprint: SHA256:0YoxhdyXsgbc0nfeB2N6FYE60mxMU7DS4uCUMaw2mvA
11 changed files with 159 additions and 24 deletions

View file

@ -41,7 +41,7 @@ repositories {
}
dependencies {
implementation 'org.geysermc.mcprotocollib:protocol:1.21.4-SNAPSHOT'
implementation 'org.geysermc.mcprotocollib:protocol:1.21.5-SNAPSHOT'
implementation 'net.kyori:adventure-text-serializer-legacy:4.19.0'
implementation 'com.google.code.gson:gson:2.12.1'
implementation 'com.google.guava:guava:33.4.0-jre'

View file

@ -76,7 +76,7 @@ public class Configuration {
}
public static class Core {
public String customName = "{\"text\":\"@\"}";
public String customName = "{text:'@'}";
}
public static class Position {
@ -172,6 +172,7 @@ public class Configuration {
public boolean useCore = true;
public boolean useCorePlaceBlock = false;
public boolean useChat = false;
public boolean useSNBTComponents = true;
public boolean coreCommandSpy = true;
public boolean resolveSRV = true;
public int reconnectDelay = 2000;

View file

@ -1,8 +1,8 @@
package me.chayapak1.chomens_bot.data.bossbar;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.util.SNBTUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.geysermc.mcprotocollib.protocol.data.game.BossBarColor;
import org.geysermc.mcprotocollib.protocol.data.game.BossBarDivision;
@ -65,7 +65,7 @@ public class BotBossBar extends BossBar {
this.title = title;
final String serialized = GsonComponentSerializer.gson().serialize(title);
final String serialized = SNBTUtilities.fromComponent(bot, title);
bot.core.run("minecraft:bossbar set " + id + " name " + serialized);

View file

@ -6,7 +6,7 @@ import me.chayapak1.chomens_bot.data.bossbar.BotBossBar;
import me.chayapak1.chomens_bot.data.listener.Listener;
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import me.chayapak1.chomens_bot.util.SNBTUtilities;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
import org.geysermc.mcprotocollib.network.packet.Packet;
@ -196,7 +196,7 @@ public class BossbarManagerPlugin implements Listener {
final Component title = bossBar.secret;
final String stringTitle = GsonComponentSerializer.gson().serialize(title);
final String stringTitle = SNBTUtilities.fromComponent(bot, title);
bot.core.run("minecraft:bossbar add " + name + " " + stringTitle);

View file

@ -9,16 +9,12 @@ import me.chayapak1.chomens_bot.data.chat.ChatParser;
import me.chayapak1.chomens_bot.data.chat.PlayerMessage;
import me.chayapak1.chomens_bot.data.listener.Listener;
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import me.chayapak1.chomens_bot.util.IllegalCharactersUtilities;
import me.chayapak1.chomens_bot.util.StringUtilities;
import me.chayapak1.chomens_bot.util.UUIDUtilities;
import me.chayapak1.chomens_bot.util.*;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.mcprotocollib.network.Session;
@ -300,7 +296,8 @@ public class ChatPlugin implements Listener {
0L,
null,
0,
new BitSet()
new BitSet(),
0
));
}
@ -359,7 +356,7 @@ public class ChatPlugin implements Listener {
final String stringified = ComponentUtilities.stringifySectionSign(component).replace("§", "&");
send(stringified);
} else {
bot.core.run("minecraft:tellraw " + targets + " " + GsonComponentSerializer.gson().serialize(component));
bot.core.run("minecraft:tellraw " + targets + " " + SNBTUtilities.fromComponent(bot, component));
}
}
@ -369,7 +366,7 @@ public class ChatPlugin implements Listener {
public void actionBar (final Component component, final String targets) {
if (bot.options.useChat) return;
bot.core.run("minecraft:title " + targets + " actionbar " + GsonComponentSerializer.gson().serialize(component));
bot.core.run("minecraft:title " + targets + " actionbar " + SNBTUtilities.fromComponent(bot, component));
}
public void actionBar (final Component component, final UUID uuid) { actionBar(component, UUIDUtilities.selector(uuid)); }

View file

@ -541,11 +541,7 @@ public class CorePlugin implements Listener {
useChat
? ""
: "{CustomName:'" +
bot.config.core.customName
.replace("\\", "\\\\")
.replace("'", "\\'") +
"'}"
: "{CustomName:" + bot.config.core.customName + "}"
);
if (useChat) bot.chat.sendCommandInstantly(command);

View file

@ -11,7 +11,6 @@ import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.*;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;

View file

@ -1,9 +1,9 @@
package me.chayapak1.chomens_bot.plugins;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.util.SNBTUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.cloudburstmc.math.vector.Vector3i;
import java.awt.*;
@ -141,7 +141,7 @@ public class ScreensharePlugin {
}
for (int i = 0; i < names.size(); i++) {
bot.core.run("minecraft:data merge entity @e[tag=" + tags.get(i) + ",limit=1] {text:'" + GsonComponentSerializer.gson().serialize(names.get(i)) + "'}");
bot.core.run("minecraft:data merge entity @e[tag=" + tags.get(i) + ",limit=1] {text:" + SNBTUtilities.fromComponent(bot, names.get(i)) + "}");
}
}

View file

@ -159,12 +159,12 @@ public class SelfCarePlugin implements Listener {
final GameEvent notification = packet.getNotification();
final GameEventValue value = packet.getValue();
if (notification == GameEvent.ENTER_CREDITS && bot.config.selfCare.endCredits) {
if (notification == GameEvent.WIN_GAME && bot.config.selfCare.endCredits) {
bot.session.send(new ServerboundClientCommandPacket(ClientCommand.RESPAWN));
return;
}
if (notification == GameEvent.CHANGE_GAMEMODE) gamemode = (GameMode) value;
if (notification == GameEvent.CHANGE_GAME_MODE) gamemode = (GameMode) value;
}
private void packetReceived (final ClientboundEntityEventPacket packet) {

View file

@ -0,0 +1,140 @@
package me.chayapak1.chomens_bot.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import me.chayapak1.chomens_bot.Bot;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.util.Map;
// for 1.21.5 SNBT components, not sure how performant this is
// since i'm not good at writing performant code, but this should
// reduce the size of the result being sent to the server by quite a bit
public class SNBTUtilities {
private static final String QUOTE = "'";
private static final String COMMA = ",";
private static final String BEGIN_OBJECT = "{";
private static final String COLON = ":";
private static final String END_OBJECT = "}";
private static final String BEGIN_ARRAY = "[";
private static final String END_ARRAY = "]";
public static String fromComponent (final Bot bot, final Component component) {
if (!bot.options.useSNBTComponents) return GsonComponentSerializer.gson().serialize(component);
final JsonElement json = GsonComponentSerializer.gson().serializeToTree(component);
return fromJson(json);
}
// RIPPED from https://minecraft.wiki/w/NBT_format#Conversion_from_JSON
public static String fromJson (final JsonElement json) {
if (json.isJsonPrimitive()) {
final JsonPrimitive primitive = json.getAsJsonPrimitive();
if (primitive.isString()) return
// don't wrap the string with quotes when not needed
// like {abc:def} instead of {abc:'def'}
needQuotes(primitive.getAsString())
? QUOTE + escapeString(primitive.getAsString()) + QUOTE
: primitive.getAsString();
else if (primitive.isBoolean()) return primitive.getAsBoolean() ? "1b" : "0b";
else if (primitive.isNumber()) return String.valueOf(primitive.getAsNumber());
} else if (json.isJsonArray()) {
final StringBuilder stringBuilder = new StringBuilder(BEGIN_ARRAY);
boolean notEmpty = false;
for (final JsonElement element : json.getAsJsonArray()) {
notEmpty = true;
stringBuilder.append(fromJson(element));
stringBuilder.append(COMMA);
}
if (notEmpty) stringBuilder.deleteCharAt(stringBuilder.length() - 1); // removes comma
stringBuilder.append(END_ARRAY);
return stringBuilder.toString();
} else if (json.isJsonObject()) {
final StringBuilder stringBuilder = new StringBuilder(BEGIN_OBJECT);
boolean notEmpty = false;
for (final Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
notEmpty = true;
// FIXME: only works in 1.21.5 adventure, at the time of writing this,
// the 1.21.5 PR is still not merged yet, so i am doing
// a lazy fix for the hover event `contents` being replaced with
// `value` and the hoverEvent and clickEvent being snake case,
// so some things work
if (entry.getKey().equals("contents")) {
stringBuilder.append("value");
// no click_event replacement yet
} else {
stringBuilder.append(convertCamelCaseToSnake(entry.getKey()));
}
stringBuilder.append(COLON);
stringBuilder.append(fromJson(entry.getValue()));
stringBuilder.append(COMMA);
}
if (notEmpty) stringBuilder.deleteCharAt(stringBuilder.length() - 1); // removes comma
stringBuilder.append(END_OBJECT);
return stringBuilder.toString();
}
return QUOTE + QUOTE;
}
private static String escapeString (final String string) {
return string
.replace("\\", "\\\\")
.replace("'", "\\'")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t")
.replace("\b", "\\b")
.replace("\f", "\\f");
}
// should this be in StringUtilities?
public static boolean needQuotes (final String string) {
if (string.isBlank()) return true;
for (int i = 0; i < string.length(); i++) {
final char c = string.charAt(i);
// even though we can do like `abc123.among.us__69` without quotes
// i am too lazy to implement that
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
return true;
}
}
return false;
}
// https://www.baeldung.com/java-camel-snake-case-conversion
// 3. Manual Approach
// FIXME: this is optional after adventure 1.21.5, remove this afterward
// it's why this is here instead of in StringUtilities
public static String convertCamelCaseToSnake (final String input) {
final StringBuilder result = new StringBuilder();
for (final char c : input.toCharArray()) {
if (Character.isUpperCase(c)) {
result.append("_").append(Character.toLowerCase(c));
} else {
result.append(c);
}
}
return result.toString();
}
}

View file

@ -141,6 +141,7 @@ bots:
# useCore - if enabled it just sends the command using chat instead of using core. recommended to enable useChat too when this is disabled
# useCorePlaceBlock - uses the place block core instead of the main core. only used if useCore is enabled
# useChat - when the bot tellraws it will chat instead of using the core to run tellraw
# useSNBTComponents - if the server is >=1.21.5, it's pretty likely that you can enable this since 1.21.5 supports SNBT components
# coreCommandSpy - set to true if server supports enabling player's commandspy through command block, defaults to true
# resolveSRV - whether to resolve SRV records on the server. the notchian minecraft doesn't resolve them
# essentialsMessages - the messages in essentials that the bot uses for self care (no example is intentional)
@ -160,6 +161,7 @@ bots:
# useCore: true
# useCorePlaceBlock: false
# useChat: false
# useSNBTComponents: true
# coreCommandSpy: true
# resolveSRV: true
# reconnectDelay: 2000