diff --git a/build-number.txt b/build-number.txt index 65c813b0..eb46a8c0 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -2361 \ No newline at end of file +2387 \ No newline at end of file diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java index d446bf41..51ff7aae 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java @@ -78,7 +78,7 @@ public class MailCommand extends Command { future.thenApply(output -> { try { - if (output == null) { + if (output.isEmpty()) { throw new CommandException(Component.text("Player has no `message` NBT tag in their selected item's minecraft:custom_data")); } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java index 3caa6211..f1d5db3f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java @@ -191,7 +191,7 @@ public class MusicCommand extends Command { ); future.thenApply(output -> { - if (output == null) { + if (output.isEmpty()) { context.sendOutput(Component.text("Player has no `SongItemData.SongData` NBT tag in their selected item's minecraft:custom_data").color(NamedTextColor.RED)); return null; } diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/CorePlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/CorePlugin.java index 6f850d97..a383dbfd 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/CorePlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/CorePlugin.java @@ -193,7 +193,8 @@ public class CorePlugin } // thanks chipmunk for this new tellraw method - public CompletableFuture runTracked (String command) { + public CompletableFuture runTracked (String command) { return runTracked(false, command); } + public CompletableFuture runTracked (boolean useCargo, String command) { if (!ready || command.length() > 32767) return null; if (!bot.options.useCore) return null; @@ -209,7 +210,7 @@ public class CorePlugin final CompletableFuture trackedFuture = new CompletableFuture<>(); - final CompletableFuture future = bot.query.block(coreBlock, "LastOutput"); + final CompletableFuture future = bot.query.block(useCargo, coreBlock, "LastOutput"); future.thenApply(output -> { if (output == null) return null; diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/PlayersPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/PlayersPlugin.java index 6179ccc6..f4a6a3f4 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/PlayersPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/PlayersPlugin.java @@ -99,7 +99,7 @@ public class PlayersPlugin extends Bot.Listener implements TickPlugin.Listener { return; } - final CompletableFuture trackedCoreFuture = bot.core.runTracked("essentials:seen " + target.profile.getIdAsString()); + final CompletableFuture trackedCoreFuture = bot.core.runTracked(true, "essentials:seen " + target.profile.getIdAsString()); if (trackedCoreFuture == null) { outputFuture.complete(null); @@ -251,7 +251,7 @@ public class PlayersPlugin extends Bot.Listener implements TickPlugin.Listener { } private CompletableFuture getLastKnownName (String uuid) { - return bot.query.entity(uuid, "bukkit.lastKnownName"); + return bot.query.entity(true, uuid, "bukkit.lastKnownName"); } private void check (PlayerEntry target) { diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/QueryPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/QueryPlugin.java index 218143e1..6a914c3f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/QueryPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/QueryPlugin.java @@ -2,51 +2,119 @@ package me.chayapak1.chomens_bot.plugins; import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.util.UUIDUtilities; -import net.kyori.adventure.text.BlockNBTComponent; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.*; import org.apache.commons.lang3.tuple.Triple; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicLong; + +public class QueryPlugin extends Bot.Listener implements ChatPlugin.Listener, TickPlugin.Listener { + private static final String ID = "chomens_bot_query"; -public class QueryPlugin extends Bot.Listener implements ChatPlugin.Listener { private final Bot bot; - public long nextTransactionId = 0; - public final Map> transactions = new HashMap<>(); - public final List ids = new ArrayList<>(); + public AtomicLong nextTransactionId = new AtomicLong(0); + public final Map> transactions = new ConcurrentHashMap<>(); + public final List ids = Collections.synchronizedList(new ArrayList<>()); + + public final Queue cargosQueue = new ConcurrentLinkedQueue<>(); public QueryPlugin (Bot bot) { this.bot = bot; bot.addListener(this); bot.chat.addListener(this); + bot.tick.addListener(this); + } + + @Override + public void onSecondTick () { + if (cargosQueue.isEmpty()) return; + + sendQueueComponent(cargosQueue); + + cargosQueue.clear(); } @Override public boolean systemMessageReceived (Component component, String string, String ansi) { - if (!(component instanceof TextComponent textComponent)) return true; + if ( + !(component instanceof TranslatableComponent rootTranslatable) || + !rootTranslatable.key().equals(ID) + ) return true; + + final List arguments = rootTranslatable.arguments(); + + if (arguments.size() != 1) return false; + + final Component cargosComponent = arguments.getFirst().asComponent(); + + if ( + !(cargosComponent instanceof TextComponent cargosTextComponent) || + !cargosTextComponent.content().isEmpty() + ) return false; + + final List cargos = cargosComponent.children(); + + for (Component cargo : cargos) processCargo(cargo); + + return false; + } + + private void sendQueueComponent (Component component) { + final Queue queue = new LinkedList<>(); + queue.add(component); + + // this is required so the joined component will be + // {"extra":["abc query here"],"text":""} + // instead of + // {"text":"abc query here"} + // even though that increases size, + // i think it will be messy to implement that + queue.add(Component.empty()); + + sendQueueComponent(queue); + } + + private void sendQueueComponent (Queue queue) { + bot.chat.tellraw( + Component + .translatable( + ID, + Component.join( + JoinConfiguration.noSeparators(), + queue + ) + ), + bot.profile.getId() + ); + } + + private void processCargo (Component cargo) { + if (!(cargo instanceof TextComponent textComponent)) return; final UUID inputId = UUIDUtilities.tryParse(textComponent.content()); - if (inputId == null || !ids.contains(inputId)) return true; + if (inputId == null || !ids.contains(inputId)) return; ids.remove(inputId); - final List children = component.children(); + final List children = cargo.children(); if ( children.size() > 2 || !(children.getFirst() instanceof TextComponent firstChild) - ) return false; + ) return; try { final long transactionId = Long.parseLong(firstChild.content()); - if (!transactions.containsKey(transactionId)) return false; + if (!transactions.containsKey(transactionId)) return; final CompletableFuture future = transactions.get(transactionId); @@ -61,15 +129,11 @@ public class QueryPlugin extends Bot.Listener implements ChatPlugin.Listener { future.complete(stringOutput); } - - return false; - } catch (NumberFormatException e) { - return true; - } + } catch (NumberFormatException ignored) { } } private Triple, Long, UUID> getFutureAndId () { - final long transactionId = nextTransactionId++; + final long transactionId = nextTransactionId.getAndIncrement(); final CompletableFuture future = new CompletableFuture<>(); transactions.put(transactionId, future); @@ -80,51 +144,55 @@ public class QueryPlugin extends Bot.Listener implements ChatPlugin.Listener { return Triple.of(future, transactionId, id); } - public CompletableFuture block (Vector3i location, String path) { + public CompletableFuture block (Vector3i location, String path) { return block(false, location, path); } + + public CompletableFuture block (boolean useCargo, Vector3i location, String path) { final Triple, Long, UUID> triple = getFutureAndId(); final UUID id = triple.getRight(); final long transactionId = triple.getMiddle(); - bot.chat.tellraw( - Component - .text(id.toString()) - .append(Component.text(transactionId)) - .append( - Component.blockNBT( - path, + final Component component = Component + .text(id.toString()) + .append(Component.text(transactionId)) + .append( + Component.blockNBT( + path, - BlockNBTComponent.WorldPos.worldPos( - BlockNBTComponent.WorldPos.Coordinate.absolute(location.getX()), - BlockNBTComponent.WorldPos.Coordinate.absolute(location.getY()), - BlockNBTComponent.WorldPos.Coordinate.absolute(location.getZ()) - ) + BlockNBTComponent.WorldPos.worldPos( + BlockNBTComponent.WorldPos.Coordinate.absolute(location.getX()), + BlockNBTComponent.WorldPos.Coordinate.absolute(location.getY()), + BlockNBTComponent.WorldPos.Coordinate.absolute(location.getZ()) ) - ), - bot.profile.getId() - ); + ) + ); + + if (useCargo) cargosQueue.add(component); + else sendQueueComponent(component); return triple.getLeft(); } - public CompletableFuture entity (String selector, String path) { + public CompletableFuture entity (String selector, String path) { return entity(false, selector, path); } + + public CompletableFuture entity (boolean useCargo, String selector, String path) { final Triple, Long, UUID> triple = getFutureAndId(); final UUID id = triple.getRight(); final long transactionId = triple.getMiddle(); - bot.chat.tellraw( - Component - .text(id.toString()) - .append(Component.text(transactionId)) - .append( - Component.entityNBT( - path, - selector - ) - ), - bot.profile.getId() - ); + final Component component = Component + .text(id.toString()) + .append(Component.text(transactionId)) + .append( + Component.entityNBT( + path, + selector + ) + ); + + if (useCargo) cargosQueue.add(component); + else sendQueueComponent(component); return triple.getLeft(); } @@ -133,7 +201,7 @@ public class QueryPlugin extends Bot.Listener implements ChatPlugin.Listener { @Override public void disconnected (DisconnectedEvent event) { - nextTransactionId = 0; + nextTransactionId.set(0); transactions.clear(); ids.clear(); }