add multiple prefixes and cspy prefixes

totallynotskidded™ some codes from ChipmunkBot™
This commit is contained in:
ChomeNS 2023-03-25 13:33:56 +07:00
parent e9fa84c93e
commit 94b7fe8ec8
19 changed files with 376 additions and 26 deletions

View file

@ -36,6 +36,8 @@ public class Bot {
@Getter private final SelfCarePlugin selfCare;
@Getter private final PositionPlugin position;
@Getter private final CorePlugin core;
@Getter private final PlayersPlugin players;
@Getter private final TabCompletePlugin tabComplete;
@Getter private final CommandHandlerPlugin commandHandler;
@Getter private final ChatCommandHandlerPlugin chatCommandHandler;
@Getter private final HashingPlugin hashing;
@ -54,6 +56,8 @@ public class Bot {
this.selfCare = new SelfCarePlugin(this);
this.position = new PositionPlugin(this);
this.core = new CorePlugin(this);
this.players = new PlayersPlugin(this);
this.tabComplete = new TabCompletePlugin(this);
this.commandHandler = new CommandHandlerPlugin();
this.chatCommandHandler = new ChatCommandHandlerPlugin(this);
this.hashing = new HashingPlugin(this);

View file

@ -2,11 +2,19 @@ package me.chayapak1.chomens_bot;
import lombok.Getter;
import java.util.List;
import java.util.Map;
public class Configuration {
@Getter public List<String> prefixes;
@Getter public List<String> commandSpyPrefixes;
@Getter public Map<String, String> consolePrefixes;
@Getter public int reconnectDelay = 7000;
@Getter public Map<String, String> keys;
@Getter public Core core = new Core();
@Getter public SelfCare selfCare = new SelfCare();
@Getter public Bots[] bots = new Bots[]{};

View file

@ -1,7 +1,10 @@
package me.chayapak1.chomens_bot.chatParsers;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.ChatParser;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent;
@ -12,8 +15,10 @@ import java.util.Map;
// Might be a confusing name, but I mean the [Chat] chayapak custom chat thing or any other
// custom chat that uses the `[%s] %s %s` translation
public class ChomeNSCustomChatParser implements ChatParser {
private final Bot bot;
public ChomeNSCustomChatParser () {
public ChomeNSCustomChatParser (Bot bot) {
this.bot = bot;
}
@Override
@ -32,9 +37,14 @@ public class ChomeNSCustomChatParser implements ChatParser {
final Component username = args.get(1);
final Component contents = args.get(2);
final String stringUsername = ComponentUtilities.stringify(username);
MutablePlayerListEntry sender = bot.players().getEntry(stringUsername);
if (sender == null) return null;
parameters.put("sender", username);
parameters.put("contents", contents);
return new PlayerMessage(parameters);
return new PlayerMessage(parameters, sender);
}
}

View file

@ -1,6 +1,10 @@
package me.chayapak1.chomens_bot.chatParsers;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.ChatParser;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
@ -10,10 +14,13 @@ import net.kyori.adventure.text.format.Style;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class KaboomChatParser implements ChatParser {
private final Bot bot;
public KaboomChatParser () {
public KaboomChatParser (Bot bot) {
this.bot = bot;
}
private static final Style empty = Style.empty();
@ -55,11 +62,15 @@ public class KaboomChatParser implements ChatParser {
return null;
}
MutablePlayerListEntry sender = bot.players().getEntry(Component.empty().append(prefix).append(displayName));
if (sender == null) sender = bot.players().getEntry(prefix.append(displayName)); // old
if (sender == null) sender = new MutablePlayerListEntry(new GameProfile(new UUID(0L, 0L), null), GameMode.SURVIVAL, 0, displayName, 0L, null, new byte[0]); // new and currently using
parameters.put("sender", displayName);
parameters.put("prefix", prefix);
parameters.put("contents", contents);
return new PlayerMessage(parameters);
return new PlayerMessage(parameters, sender);
}
private boolean isSeperatorAt (List<Component> children, int start) {

View file

@ -1,6 +1,10 @@
package me.chayapak1.chomens_bot.chatParsers;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.ChatParser;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent;
@ -9,8 +13,11 @@ import net.kyori.adventure.text.event.HoverEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MinecraftChatParser implements ChatParser {
private final Bot bot;
// ? Is such a mapping necessary?
private static final Map<String, String> typeMap = new HashMap<>();
static {
@ -21,7 +28,8 @@ public class MinecraftChatParser implements ChatParser {
typeMap.put("chat.type.emote", "minecraft:emote_command");
}
public MinecraftChatParser () {
public MinecraftChatParser (Bot bot) {
this.bot = bot;
}
@Override
@ -40,9 +48,18 @@ public class MinecraftChatParser implements ChatParser {
final Component senderComponent = args.get(0);
final Component contents = args.get(1);
// try to find the sender then make it a player list entry
final HoverEvent<?> hoverEvent = senderComponent.hoverEvent();
if (hoverEvent == null || !hoverEvent.action().equals(HoverEvent.Action.SHOW_ENTITY)) return null;
HoverEvent.ShowEntity entityInfo = (HoverEvent.ShowEntity) hoverEvent.value();
final UUID senderUUID = entityInfo.id();
MutablePlayerListEntry sender = bot.players().getEntry(senderUUID);
if (sender == null) sender = new MutablePlayerListEntry(new GameProfile(senderUUID, null), GameMode.SURVIVAL, 0, entityInfo.name(), 0L, null, new byte[0]);
parameters.put("sender", senderComponent);
parameters.put("contents", contents);
return new PlayerMessage(parameters);
return new PlayerMessage(parameters, sender);
}
}

View file

@ -0,0 +1,55 @@
package me.chayapak1.chomens_bot.chatParsers.commandSpy;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.ChatParser;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CommandSpyParser implements ChatParser {
private final Bot bot;
public CommandSpyParser (Bot bot) {
this.bot = bot;
}
@Override
public PlayerMessage parse (Component message) {
if (message instanceof TextComponent) return parse((TextComponent) message);
return null;
}
public PlayerMessage parse (TextComponent message) {
final List<Component> children = message.children();
if (
(
message.color() != NamedTextColor.AQUA ||
message.color() != NamedTextColor.YELLOW
) &&
children.size() < 2
) return null;
final Component username = Component.text(message.content());
final Component command = children.get(1);
final String stringUsername = ComponentUtilities.stringify(username);
MutablePlayerListEntry sender = bot.players().getEntry(stringUsername);
if (sender == null) return null;
final Map<String, Component> parameters = new HashMap<>();
parameters.put("sender", username);
parameters.put("contents", command);
return new PlayerMessage(parameters, sender);
}
}

View file

@ -0,0 +1,26 @@
package me.chayapak1.chomens_bot.chatParsers.data;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntry;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import lombok.AllArgsConstructor;
import lombok.Data;
import net.kyori.adventure.text.Component;
import java.security.PublicKey;
@Data
@AllArgsConstructor
public class MutablePlayerListEntry {
private GameProfile profile;
private GameMode gamemode;
private int latency;
private Component displayName;
private long expiresAt;
private PublicKey publicKey;
private byte[] keySignature;
public MutablePlayerListEntry (PlayerListEntry entry) {
this(entry.getProfile(), entry.getGameMode(), entry.getPing(), entry.getDisplayName(), entry.getExpiresAt(), entry.getPublicKey(), entry.getKeySignature());
}
}

View file

@ -10,4 +10,5 @@ import java.util.Map;
@AllArgsConstructor
public class PlayerMessage {
private Map<String, Component> parameters;
private MutablePlayerListEntry sender;
}

View file

@ -7,11 +7,14 @@ import net.kyori.adventure.text.Component;
public class CommandContext {
@Getter public final Bot bot;
@Getter public final String prefix;
@Getter private final String hash;
@Getter private final String ownerHash;
public CommandContext(Bot bot, String hash, String ownerHash) {
public CommandContext(Bot bot, String prefix, String hash, String ownerHash) {
this.bot = bot;
this.prefix = prefix;
this.hash = hash;
this.ownerHash = ownerHash;
}

View file

@ -8,8 +8,8 @@ import net.kyori.adventure.text.format.NamedTextColor;
public class ConsoleCommandContext extends CommandContext {
private final Bot bot;
public ConsoleCommandContext (Bot bot, String hash, String ownerHash) {
super(bot, hash, ownerHash);
public ConsoleCommandContext (Bot bot, String prefix, String hash, String ownerHash) {
super(bot, prefix, hash, ownerHash);
this.bot = bot;
}

View file

@ -7,17 +7,20 @@ import net.kyori.adventure.text.Component;
public class PlayerCommandContext extends CommandContext {
@Getter private final String playerName;
@Getter private final String selector;
private final Bot bot;
public PlayerCommandContext (Bot bot, String playerName, String hash, String ownerHash) {
super(bot, hash, ownerHash);
public PlayerCommandContext (Bot bot, String playerName, String prefix, String selector, String hash, String ownerHash) {
super(bot, prefix, hash, ownerHash);
this.bot = bot;
this.playerName = playerName;
this.selector = selector;
}
@Override
public void sendOutput (Component message) {
bot.chat().tellraw(message);
bot.chat().tellraw(message, selector);
}
@Override

View file

@ -96,7 +96,7 @@ public class HelpCommand implements Command {
public Component sendUsages (CommandContext context, String[] args) {
final Bot bot = context.bot();
final String prefix = bot.chatCommandHandler().prefix();
final String prefix = context.prefix();
for (Command command : bot.commandHandler().commands()) {
if (!command.name().equals(args[0]) && !command.alias().contains(args[0])) continue;

View file

@ -148,7 +148,7 @@ public class MusicCommand implements Command {
}
public Component list (CommandContext context, String[] args) {
final String prefix = context.bot().chatCommandHandler().prefix();
final String prefix = context.prefix();
final Path _path = Path.of(root.toString(), String.join(" ", args));
final Path path = (args.length < 2) ? root : _path;

View file

@ -5,22 +5,34 @@ import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import me.chayapak1.chomens_bot.command.PlayerCommandContext;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import me.chayapak1.chomens_bot.util.UUIDUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
public class ChatCommandHandlerPlugin extends ChatPlugin.ChatListener {
@Getter private final String prefix = "j*";
import java.util.List;
public class ChatCommandHandlerPlugin extends ChatPlugin.ChatListener {
public final Bot bot;
@Getter private final List<String> prefixes;
@Getter private final List<String> commandSpyPrefixes;
public ChatCommandHandlerPlugin(Bot bot) {
this.bot = bot;
this.prefixes = bot.config().prefixes();
this.commandSpyPrefixes = bot.config().commandSpyPrefixes();
bot.chat().addListener(this);
}
@Override
public void playerMessageReceived (PlayerMessage message) {
public void playerMessageReceived (PlayerMessage message) { listener(message, false); }
@Override
public void commandSpyMessageReceived (PlayerMessage message) { listener(message, true); }
private void listener (PlayerMessage message, boolean cspy) {
final Component displayNameComponent = message.parameters().get("sender");
final Component messageComponent = message.parameters().get("contents");
if (displayNameComponent == null || messageComponent == null) return;
@ -28,10 +40,20 @@ public class ChatCommandHandlerPlugin extends ChatPlugin.ChatListener {
final String displayName = ComponentUtilities.stringify(displayNameComponent);
final String contents = ComponentUtilities.stringify(messageComponent);
if (!contents.startsWith(prefix)) return;
String prefix = null;
for (String eachPrefix : (cspy ? commandSpyPrefixes : prefixes)) {
if (!contents.startsWith(eachPrefix)) continue;
prefix = eachPrefix;
}
if (prefix == null) return;
final String commandString = contents.substring(prefix.length());
final PlayerCommandContext context = new PlayerCommandContext(bot, displayName, bot.hashing().hash(), bot.hashing().ownerHash());
final String selector = cspy ? UUIDUtilities.selector(message.sender().profile().getId()) : "@a";
final PlayerCommandContext context = new PlayerCommandContext(bot, displayName, prefix, selector, bot.hashing().hash(), bot.hashing().ownerHash());
final Component output = bot.commandHandler().executeCommand(commandString, context, bot.hashing().hash(), bot.hashing().ownerHash());
final String textOutput = ((TextComponent) output).content();

View file

@ -10,6 +10,7 @@ import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.ChomeNSCustomChatParser;
import me.chayapak1.chomens_bot.chatParsers.KaboomChatParser;
import me.chayapak1.chomens_bot.chatParsers.MinecraftChatParser;
import me.chayapak1.chomens_bot.chatParsers.commandSpy.CommandSpyParser;
import me.chayapak1.chomens_bot.chatParsers.data.ChatParser;
import me.chayapak1.chomens_bot.chatParsers.data.PlayerMessage;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
@ -28,16 +29,21 @@ public class ChatPlugin extends SessionAdapter {
private final List<ChatParser> chatParsers;
private final CommandSpyParser commandSpyParser;
private final List<ChatListener> listeners = new ArrayList<>();
public ChatPlugin (Bot bot) {
this.bot = bot;
this.commandSpyParser = new CommandSpyParser(bot);
bot.addListener(this);
chatParsers = new ArrayList<>();
chatParsers.add(new MinecraftChatParser());
chatParsers.add(new KaboomChatParser());
chatParsers.add(new ChomeNSCustomChatParser());
chatParsers.add(new MinecraftChatParser(bot));
chatParsers.add(new KaboomChatParser(bot));
chatParsers.add(new ChomeNSCustomChatParser(bot));
}
@Override
@ -66,10 +72,14 @@ public class ChatPlugin extends SessionAdapter {
if (playerMessage != null) break;
}
PlayerMessage commandSpyMessage;
commandSpyMessage = commandSpyParser.parse(component);
final String message = ComponentUtilities.stringify(component);
for (ChatListener listener : listeners) {
listener.systemMessageReceived(message, component);
if (playerMessage != null) listener.playerMessageReceived(playerMessage);
if (commandSpyMessage != null) listener.commandSpyMessageReceived(commandSpyMessage);
}
}
@ -109,6 +119,7 @@ public class ChatPlugin extends SessionAdapter {
public static class ChatListener {
public void playerMessageReceived (PlayerMessage message) {}
public void commandSpyMessageReceived (PlayerMessage message) {}
public void systemMessageReceived (String message, Component component) {}
}
}

View file

@ -20,14 +20,17 @@ public class ConsolePlugin {
@Getter private String consoleServer = "all";
@Getter private final String prefix = ".";
@Getter private final String consoleServerPrefix = "/";
@Getter private String prefix;
@Getter private String consoleServerPrefix;
public ConsolePlugin (List<Bot> allBots) {
this.allBots = allBots;
this.reader = LineReaderBuilder.builder().build();
for (Bot bot : allBots) {
prefix = bot.config().consolePrefixes().get("normalCommandsPrefix");
consoleServerPrefix = bot.config().consolePrefixes().get("consoleServerPrefix");
bot.console(this);
bot.logger(new LoggerPlugin(bot));
}
@ -79,7 +82,7 @@ public class ConsolePlugin {
if (!bot.host().equals(consoleServer) && !consoleServer.equals("all")) continue;
if (line.startsWith(prefix)) {
final ConsoleCommandContext context = new ConsoleCommandContext(bot, "h", "o"); // ? should the hashes be hardcoded?
final ConsoleCommandContext context = new ConsoleCommandContext(bot, prefix, "h", "o"); // ? should the hashes be hardcoded?
final Component output = bot.commandHandler().executeCommand(line.substring(prefix.length()), context, "h", "o");
final String textOutput = ((TextComponent) output).content();

View file

@ -0,0 +1,122 @@
package me.chayapak1.chomens_bot.plugins;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntry;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoPacket;
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.packet.Packet;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chatParsers.data.MutablePlayerListEntry;
import net.kyori.adventure.text.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PlayersPlugin extends SessionAdapter {
private final Bot bot;
public List<MutablePlayerListEntry> list = new ArrayList<>();
public PlayersPlugin (Bot bot) {
this.bot = bot;
bot.addListener(this);
}
@Override
public void packetReceived (Session session, Packet packet) {
if (packet instanceof ClientboundPlayerInfoPacket) packetReceived((ClientboundPlayerInfoPacket) packet);
}
public void packetReceived (ClientboundPlayerInfoPacket packet) {
PlayerListEntryAction action = packet.getAction();
for (PlayerListEntry entry : packet.getEntries()) {
if (action == PlayerListEntryAction.ADD_PLAYER) addPlayer(entry);
else if (action == PlayerListEntryAction.UPDATE_GAMEMODE) updateGamemode(entry);
else if (action == PlayerListEntryAction.UPDATE_LATENCY) updateLatency(entry);
else if (action == PlayerListEntryAction.UPDATE_DISPLAY_NAME) updateDisplayName(entry);
else if (action == PlayerListEntryAction.REMOVE_PLAYER) removePlayer(entry);
}
}
public final MutablePlayerListEntry getEntry (UUID uuid) {
for (MutablePlayerListEntry candidate : list) {
if (candidate.profile().getId().equals(uuid)) {
return candidate;
}
}
return null;
}
public final MutablePlayerListEntry getEntry (String username) {
for (MutablePlayerListEntry candidate : list) {
if (candidate.profile().getName().equals(username)) {
return candidate;
}
}
return null;
}
public final MutablePlayerListEntry getEntry (Component displayName) {
for (MutablePlayerListEntry candidate : list) {
if (candidate.displayName() != null && candidate.displayName().equals(displayName)) {
return candidate;
}
}
return null;
}
private MutablePlayerListEntry getEntry (PlayerListEntry other) {
return getEntry(other.getProfile().getId());
}
private void addPlayer (PlayerListEntry newEntry) {
final MutablePlayerListEntry duplicate = getEntry(newEntry);
if (duplicate != null) list.remove(duplicate);
list.add(new MutablePlayerListEntry(newEntry));
}
private void updateGamemode (PlayerListEntry newEntry) {
final MutablePlayerListEntry target = getEntry(newEntry);
if (target == null) return;
target.gamemode(newEntry.getGameMode());
}
private void updateLatency (PlayerListEntry newEntry) {
final MutablePlayerListEntry target = getEntry(newEntry);
if (target == null) return;
target.latency(newEntry.getPing());
}
private void updateDisplayName (PlayerListEntry newEntry) {
final MutablePlayerListEntry target = getEntry(newEntry);
if (target == null) return;
target.displayName(newEntry.getDisplayName());
}
private void removePlayer (PlayerListEntry newEntry) {
final MutablePlayerListEntry target = getEntry(newEntry);
if (target == null) return;
bot.tabComplete().tabComplete("/minecraft:scoreboard players add ").thenApply(packet -> {
final String[] matches = packet.getMatches();
final Component[] tooltips = packet.getTooltips();
final String username = target.profile().getName();
for (int i = 0; i < matches.length; i++) {
if (tooltips[i] != null || !matches[i].equals(username)) continue;
return packet;
}
list.remove(target);
return packet;
});
}
}

View file

@ -0,0 +1,42 @@
package me.chayapak1.chomens_bot.plugins;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCommandSuggestionsPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCommandSuggestionPacket;
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.packet.Packet;
import me.chayapak1.chomens_bot.Bot;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class TabCompletePlugin extends SessionAdapter {
private final Bot bot;
private int nextTransactionId = 0;
private final Map<Integer, CompletableFuture<ClientboundCommandSuggestionsPacket>> transactions = new HashMap<>();
public TabCompletePlugin (Bot bot) {
this.bot = bot;
bot.addListener(this);
}
public CompletableFuture<ClientboundCommandSuggestionsPacket> tabComplete (String command) {
final int transactionId = nextTransactionId++;
bot.session().send(new ServerboundCommandSuggestionPacket(transactionId, command));
final CompletableFuture<ClientboundCommandSuggestionsPacket> future = new CompletableFuture<>();
transactions.put(transactionId, future);
return future;
}
@Override
public void packetReceived (Session session, Packet packet) {
if (packet instanceof ClientboundCommandSuggestionsPacket) packetReceived((ClientboundCommandSuggestionsPacket) packet);
}
public void packetReceived (ClientboundCommandSuggestionsPacket packet) {
transactions.get(packet.getTransactionId()).complete(packet);
}
}

View file

@ -1,4 +1,16 @@
prefixes:
- 'default*'
- 'defaultcbot '
commandSpyPrefixes:
- '/defaultcbot '
consolePrefixes:
normalCommandsPrefix: '.'
consoleServerPrefix: '/'
reconnectDelay: 7000
keys:
normalKey: 'normal hash key here'
ownerKey: 'OwnerHash™ key here'
@ -31,4 +43,4 @@ bots:
- host: 'localhost'
port: 25565
username: 'ChomeNS_Bot'
kaboom: false
kaboom: false