forked from chipmunkmc/chipmunkbot
Chat parsing :D
This commit is contained in:
parent
2f6dac6ae5
commit
ef4ce27a4a
6 changed files with 235 additions and 7 deletions
|
@ -0,0 +1,16 @@
|
|||
package land.chipmunk.chipmunkbot.data.chat;
|
||||
|
||||
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
|
||||
import lombok.Data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class PlayerMessage {
|
||||
private String type;
|
||||
private MutablePlayerListEntry sender;
|
||||
private Map<String, Component> parameters;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package land.chipmunk.chipmunkbot.data.chat;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public interface SystemChatParser {
|
||||
PlayerMessage parse (Component message);
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package land.chipmunk.chipmunkbot.plugins;
|
||||
|
||||
import land.chipmunk.chipmunkbot.Client;
|
||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
||||
import land.chipmunk.chipmunkbot.data.chat.SystemChatParser;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
|
@ -8,14 +10,29 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCh
|
|||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
import com.github.steveice10.packetlib.Session;
|
||||
import com.github.steveice10.packetlib.event.session.SessionAdapter;
|
||||
import com.github.steveice10.packetlib.event.session.SessionListener;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import java.util.BitSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.time.Instant;
|
||||
|
||||
public class ChatPlugin {
|
||||
private Client client;
|
||||
public ChatPlugin (Client client) { this.client = client; }
|
||||
import land.chipmunk.chipmunkbot.systemChat.*;
|
||||
|
||||
public class ChatPlugin extends SessionAdapter {
|
||||
private final ChipmunkBot client;
|
||||
private List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
private List<SystemChatParser> systemChatParsers;
|
||||
|
||||
public ChatPlugin (ChipmunkBot client) {
|
||||
this.client = client;
|
||||
client.session().addListener((SessionListener) this);
|
||||
|
||||
systemChatParsers = new ArrayList<>();
|
||||
systemChatParsers.add(new MinecraftChatParser(client));
|
||||
systemChatParsers.add(new KaboomChatParser(client));
|
||||
}
|
||||
|
||||
public void message (String message) {
|
||||
final ServerboundChatPacket packet = new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0, new byte[0], false, new ArrayList<>(), null);
|
||||
|
@ -26,4 +43,36 @@ public class ChatPlugin {
|
|||
final ServerboundChatCommandPacket packet = new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0, new ArrayList<>(), false, new ArrayList<>(), null);
|
||||
client.session().send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetReceived (Session session, Packet packet) {
|
||||
// TODO: Player chat
|
||||
if (packet instanceof ClientboundSystemChatPacket) packetReceived(session, (ClientboundSystemChatPacket) packet);
|
||||
}
|
||||
|
||||
public void packetReceived (Session session, ClientboundSystemChatPacket packet) {
|
||||
final Component component = packet.getContent();
|
||||
final boolean overlay = packet.isOverlay();
|
||||
|
||||
PlayerMessage playerMessage = null;
|
||||
|
||||
for (SystemChatParser parser : systemChatParsers) {
|
||||
playerMessage = parser.parse(component);
|
||||
if (playerMessage != null) break;
|
||||
}
|
||||
|
||||
for (Listener listener : this.listeners) {
|
||||
listener.systemMessageReceived(component, overlay);
|
||||
if (playerMessage != null) listener.playerMessageReceived(playerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener (Listener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public class Listener {
|
||||
public void systemMessageReceived (Component component, boolean overlay) {}
|
||||
public void playerMessageReceived (PlayerMessage message) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,10 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPl
|
|||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
import com.github.steveice10.packetlib.Session;
|
||||
import com.github.steveice10.packetlib.event.session.SessionAdapter;
|
||||
import com.github.steveice10.packetlib.event.session.SessionListener;
|
||||
import com.github.steveice10.mc.protocol.data.game.PlayerListEntry;
|
||||
import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -15,9 +17,12 @@ import java.util.UUID;
|
|||
|
||||
public class PlayerListPlugin extends SessionAdapter {
|
||||
private Client client;
|
||||
public List<MutablePlayerListEntry> list = new ArrayList<MutablePlayerListEntry>();
|
||||
public List<MutablePlayerListEntry> list = new ArrayList<>();
|
||||
|
||||
public PlayerListPlugin (Client client) { this.client = client; }
|
||||
public PlayerListPlugin (Client client) {
|
||||
this.client = client;
|
||||
client.session().addListener((SessionListener) this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetReceived (Session session, Packet packet) {
|
||||
|
@ -26,7 +31,6 @@ public class PlayerListPlugin extends SessionAdapter {
|
|||
|
||||
public void packetReceived (Session session, 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);
|
||||
|
@ -56,6 +60,16 @@ public class PlayerListPlugin extends SessionAdapter {
|
|||
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 final MutablePlayerListEntry getEntry (PlayerListEntry other) {
|
||||
return getEntry(other.getProfile().getId());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package land.chipmunk.chipmunkbot.systemChat;
|
||||
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
|
||||
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
||||
import land.chipmunk.chipmunkbot.data.chat.SystemChatParser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
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 SystemChatParser {
|
||||
private final ChipmunkBot client;
|
||||
|
||||
public KaboomChatParser (ChipmunkBot client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
private static Style empty = Style.empty();
|
||||
private static Component SEPERATOR_COLON = Component.text(":");
|
||||
private static Component SEPERATOR_SPACE = Component.space();
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
if (message instanceof TextComponent) return parse((TextComponent) message);
|
||||
if (message instanceof TranslatableComponent) return parse((TranslatableComponent) message);
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerMessage parse (TranslatableComponent message) {
|
||||
if (!message.key().equals("%") || message.args().size() != 1 || !message.style().equals(empty)) return parse(message.args().get(0));
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerMessage parse (TextComponent message) {
|
||||
List<Component> children = message.children();
|
||||
|
||||
if (!message.content().equals("") || !message.style().equals(empty) || children.size() < 3) return null;
|
||||
|
||||
final Map<String, Component> parameters = new HashMap<>();
|
||||
|
||||
final Component prefix = children.get(0);
|
||||
Component displayName = Component.empty();
|
||||
Component contents = Component.empty();
|
||||
|
||||
if (isSeperatorAt(children, 1)) { // Missing/blank display name
|
||||
if (children.size() >= 2) contents = children.get(1);
|
||||
} else if (isSeperatorAt(children, 2)) {
|
||||
displayName = children.get(1);
|
||||
if (children.size() >= 3) contents = children.get(2);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
MutablePlayerListEntry sender = client.playerList().getEntry(prefix.append(displayName));
|
||||
if (sender == null) sender = new MutablePlayerListEntry(new GameProfile(new UUID(0l, 0l), null), GameMode.SURVIVAL, 0, displayName, 0L, null, new byte[0]);
|
||||
|
||||
parameters.put("sender", displayName);
|
||||
parameters.put("prefix", prefix);
|
||||
parameters.put("contents", contents);
|
||||
|
||||
return new PlayerMessage("minecraft:chat", sender, parameters);
|
||||
}
|
||||
|
||||
private boolean isSeperatorAt (List<Component> children, int start) {
|
||||
return children.get(start).equals(SEPERATOR_COLON) && children.get(start + 1).equals(SEPERATOR_SPACE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package land.chipmunk.chipmunkbot.systemChat;
|
||||
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import land.chipmunk.chipmunkbot.ChipmunkBot;
|
||||
import land.chipmunk.chipmunkbot.data.MutablePlayerListEntry;
|
||||
import land.chipmunk.chipmunkbot.data.chat.PlayerMessage;
|
||||
import land.chipmunk.chipmunkbot.data.chat.SystemChatParser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
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 SystemChatParser {
|
||||
// ? Is such a mapping necessary?
|
||||
private static final Map<String, String> typeMap = new HashMap<>();
|
||||
static {
|
||||
typeMap.put("chat.type.text", "minecraft:chat");
|
||||
typeMap.put("chat.type.announcement", "minecraft:say_command");
|
||||
typeMap.put("chat.type.command", "minecraft:msg_command");
|
||||
typeMap.put("chat.type.team.text", "minecraft:team_msg_command");
|
||||
typeMap.put("chat.type.emote", "minecraft:emote_command");
|
||||
}
|
||||
|
||||
private final ChipmunkBot client;
|
||||
|
||||
public MinecraftChatParser (ChipmunkBot client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
if (message instanceof TranslatableComponent) return parse((TranslatableComponent) message);
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerMessage parse (TranslatableComponent message) {
|
||||
final List<Component> args = message.args();
|
||||
final String key = message.key();
|
||||
if (args.size() < 2 || !typeMap.containsKey(key)) return null;
|
||||
|
||||
final String type = typeMap.get(key);
|
||||
|
||||
final Map<String, Component> parameters = new HashMap<>();
|
||||
|
||||
final Component senderComponent = args.get(0);
|
||||
final Component contents = args.get(1);
|
||||
|
||||
// Find the sender and attempt to map it to a player
|
||||
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 = client.playerList().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(type, sender, parameters);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue