Compare commits

...

32 commits

Author SHA1 Message Date
c738a37948
"fix": this seems to do nothing 2024-11-14 18:43:57 +07:00
373736feed
feat: add *info (no arguments) 2024-11-14 16:41:33 +07:00
c0909d54aa
style fix: i forgor the color change 2024-11-14 16:18:17 +07:00
159cb8ce11
refactor: make cloop remove return command name 2024-11-14 16:11:16 +07:00
627b18ebf9
refactor: make whitelist remove by index like in the usage 2024-11-14 16:11:00 +07:00
66dc3b97ec
refactor: refactor PersistentDataUtilities, hopefully it will work ok
i do have a backup so this should be fine if it fails somehow
2024-11-12 20:04:22 +07:00
f322e2dd14
fix: more fix in Main 2024-11-12 19:28:09 +07:00
5e9a1f0917
fix: stopping stuff in Main and IRCPlugin 2024-11-12 16:43:45 +07:00
4ba78b843b
refactor,fix: music stuff, and add music locking (servereval only) 2024-11-12 16:40:46 +07:00
357559ae6e
fix: ignore exceptions in irc queue tick 2024-11-12 16:36:55 +07:00
7363252660
fix: fix loopPosition in Song 2024-11-12 16:09:00 +07:00
4b2b1e9e1a
fix: cool 2024-11-11 20:34:10 +07:00
28012c1194
fix: remove null uuid for extras chat format, which breaks a lot of commands 2024-11-11 17:58:51 +07:00
7b78ce7d06
fix: prevent whitelist from kicking the bot itself 2024-11-10 19:25:42 +07:00
11f478487d
fix: throw CommandException itself in GrepLogPlugin 2024-11-10 12:10:28 +07:00
4f8d5bfff5
fix: makeNewLogFile() in FileLoggerUtilities appending to the file instead of deleting the existing one 2024-11-10 08:31:43 +07:00
3811790c93
feat: *console printdisconnectedcause <true|false>
very useful for debugging
2024-11-07 17:52:12 +07:00
597a694727
fix: (maybe) ACTUALLY fix file logging (for the 69th time) 2024-11-05 16:44:56 +07:00
f561a9c810
refactor (eval): getBotUsername -> getBotInfo & make core() tracked in eval 2024-11-04 19:23:31 +07:00
4b16f12623
fix: mabe 2024-11-04 19:06:43 +07:00
783a7a937e
refactor: improve AuthPlugin by at least a bit 2024-11-04 16:57:28 +07:00
cb86896223
"fix": doesn't work 2024-11-03 19:34:57 +07:00
e62de655ba
fix: the commit before this 2024-11-02 19:30:24 +07:00
0ddf042311
feat: automatically make the bot go down if currentY > maxY 2024-11-02 19:27:08 +07:00
4764a8947e
refactor: make maps in PositionPlugin public for access with servereval 2024-11-02 18:31:28 +07:00
b3615770dc
fix: fix most OOBs, and also fix maxY in WorldPlugin 2024-11-02 18:18:47 +07:00
3ad8b11494
fix: finally fix voicechat 2024-11-02 17:37:09 +07:00
b118d50249
feat: getLatestChatMessage eval function 2024-11-02 17:12:23 +07:00
9e22cdfea5
feat: getBotUsername eval function 2024-11-02 15:29:47 +07:00
c655b5d0cd
chore (default_config.yml): some modifications to the comment at ownerName and backup 2024-11-02 14:37:06 +07:00
71ef35598c
style: use DecimalFormatter on greplog
from now on i am going to have the types on commits because why not
2024-11-02 14:29:02 +07:00
c707309958 Merge branch 'amy' 2024-11-02 12:59:56 +07:00
35 changed files with 334 additions and 172 deletions

View file

@ -41,6 +41,8 @@ public class Bot {
public Session session;
public boolean printDisconnectedCause = false;
public boolean loggedIn = false;
public final ExecutorService executorService = Main.executorService;
@ -251,6 +253,8 @@ public class Bot {
final Throwable cause = disconnectedEvent.getCause();
if (printDisconnectedCause && cause != null) cause.printStackTrace();
// lazy fix #69420
if (cause instanceof OutOfMemoryError) System.exit(1);

View file

@ -43,6 +43,8 @@ public class Main {
private static boolean alreadyStarted = false;
private static boolean stopping = false;
private static final List<Thread> alreadyAddedThreads = new ArrayList<>();
private static JDA jda = null;
@ -187,6 +189,10 @@ public class Main {
// most of these are stolen from HBot
public static void stop () {
if (stopping) return;
stopping = true;
executor.shutdown();
PersistentDataUtilities.stop();
@ -209,17 +215,17 @@ public class Main {
final boolean discordEnabled = config.discord.enabled;
for (Bot bot : copiedList) {
if (discordEnabled) {
final String channelId = bot.discord.servers.get(bot.host + ":" + bot.port);
try {
if (discordEnabled) {
final String channelId = bot.discord.servers.get(bot.host + ":" + bot.port);
bot.discord.sendMessageInstantly("Stopping..", channelId);
}
bot.discord.sendMessageInstantly("Stopping..", channelId);
}
if (ircEnabled) {
bot.irc.quit("Stopping..");
}
if (ircEnabled) bot.irc.quit("Stopping..");
bot.stop();
bot.stop();
} catch (Exception ignored) {}
}
if (jda != null) jda.shutdown();

View file

@ -1,5 +1,6 @@
package me.chayapak1.chomens_bot.chatParsers;
import me.chayapak1.chomens_bot.util.UUIDUtilities;
import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import me.chayapak1.chomens_bot.Bot;
@ -38,7 +39,7 @@ public class CreayunChatParser implements ChatParser {
final String contents = matcher.group(2);
PlayerEntry sender = bot.players.getEntry(displayName);
if (sender == null) sender = new PlayerEntry(new GameProfile(new UUID(0L, 0L), displayName), GameMode.SURVIVAL, 0, Component.text(displayName), 0L, null, new byte[0], true);
if (sender == null) sender = new PlayerEntry(new GameProfile(UUIDUtilities.getOfflineUUID(displayName), displayName), GameMode.SURVIVAL, 0, Component.text(displayName), 0L, null, new byte[0], true);
return new PlayerMessage(sender, Component.text(displayName), Component.text(contents));
}

View file

@ -1,5 +1,7 @@
package me.chayapak1.chomens_bot.chatParsers;
import me.chayapak1.chomens_bot.util.ComponentUtilities;
import me.chayapak1.chomens_bot.util.UUIDUtilities;
import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import me.chayapak1.chomens_bot.Bot;
@ -43,9 +45,12 @@ public class KaboomChatParser implements ChatParser {
return null;
}
// final String stringifiedDisplayName = ComponentUtilities.stringify(displayName);
PlayerEntry 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 PlayerEntry(new GameProfile(new UUID(0L, 0L), null), GameMode.SURVIVAL, 0, displayName, 0L, null, new byte[0], true); // new and currently using
// if (sender == null) sender = new PlayerEntry(new GameProfile(UUIDUtilities.getOfflineUUID(stringifiedDisplayName), stringifiedDisplayName), GameMode.SURVIVAL, 0, displayName, 0L, null, new byte[0], true); // new and currently using
if (sender == null) return null;
return new PlayerMessage(sender, displayName, contents);
}

View file

@ -52,11 +52,12 @@ public class CloopCommand extends Command {
try {
final int index = context.getInteger(true);
bot.cloop.remove(index);
final CommandLoop cloop = bot.cloop.remove(index);
return Component.translatable(
"Removed cloop %s",
Component.text(index).color(ColorUtilities.getColorByString(bot.config.colorPalette.number))
Component.text(cloop.command()).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
throw new CommandException(Component.text("Invalid index"));
@ -96,9 +97,7 @@ public class CloopCommand extends Command {
Component.join(JoinConfiguration.newlines(), cloopsComponent)
);
}
default -> {
throw new CommandException(Component.text("Invalid action"));
}
default -> throw new CommandException(Component.text("Invalid action"));
}
}
}

View file

@ -19,7 +19,8 @@ public class ConsoleCommand extends Command {
"Controls stuff about console",
new String[] {
"server <server>",
"logtoconsole <true|false>"
"logtoconsole <true|false>",
"printdisconnectedreason <true|false>"
},
new String[] {},
TrustLevel.OWNER,
@ -56,7 +57,8 @@ public class ConsoleCommand extends Command {
// servers.find(server => server.toLowerCase().includes(args.join(' '))) in js i guess
eachBot.console.consoleServer = servers.stream()
.filter(eachServer -> eachServer.toLowerCase().contains(server))
.toArray(String[]::new)[0];
.findFirst()
.orElse("all");
context.sendOutput(Component.text("Set the console server to " + bot.console.consoleServer).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)));
} catch (ArrayIndexOutOfBoundsException e) {
@ -76,6 +78,18 @@ public class ConsoleCommand extends Command {
bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED)
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
}
case "printdisconnectedreason" -> {
context.checkOverloadArgs(2);
final boolean bool = context.getBoolean(true);
bot.printDisconnectedCause = bool;
return Component.translatable(
"Printing the disconnected cause is now %s",
bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED)
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
}
}
return null;

View file

@ -10,7 +10,9 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import java.io.IOException;
import java.io.RandomAccessFile;
@ -26,11 +28,14 @@ import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class InfoCommand extends Command {
public static final String ORIGINAL_REPOSITORY_URL = "https://code.chipmunk.land/ChomeNS/chomens-bot-java";
public InfoCommand () {
super(
"info",
"Shows an info about various things",
new String[] {
"",
"<creator>",
"<discord>",
"<server>",
@ -49,7 +54,7 @@ public class InfoCommand extends Command {
final Bot bot = context.bot;
final String action = context.getString(false, true, true);
final String action = context.getString(false, false, true);
switch (action) {
case "creator" -> {
@ -199,7 +204,31 @@ public class InfoCommand extends Command {
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
}
default -> {
throw new CommandException(Component.text("Invalid action"));
return Component.empty()
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
.append(Component.text("ChomeNS Bot").color(NamedTextColor.YELLOW))
.append(Component.space())
.append(
Component
.translatable(
"is an open-source utility bot and a moderation bot made for " +
"the %s Minecraft server (and its clones) " +
"but also works on vanilla Minecraft servers. " +
"It was originally made for fun but " +
"I got addicted and made it a full blown bot."
)
.arguments(Component.text("Kaboom").style(Style.style().color(NamedTextColor.GRAY).decorate(TextDecoration.BOLD)))
)
.append(Component.newline())
.append(Component.text("Original repository: "))
.append(
Component
.text(ORIGINAL_REPOSITORY_URL)
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
.clickEvent(
ClickEvent.openUrl(ORIGINAL_REPOSITORY_URL)
)
);
}
}
}

View file

@ -12,7 +12,6 @@ import me.chayapak1.chomens_bot.song.Loop;
import me.chayapak1.chomens_bot.song.Note;
import me.chayapak1.chomens_bot.song.Song;
import me.chayapak1.chomens_bot.util.*;
import me.chayapak1.chomens_bot.util.*;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.TranslatableComponent;
@ -36,8 +35,6 @@ import static me.chayapak1.chomens_bot.util.StringUtilities.isNotNullAndNotBlank
public class MusicCommand extends Command {
private Path root;
private int ratelimit = 0;
public MusicCommand () {
super(
"music",
@ -63,15 +60,11 @@ public class MusicCommand extends Command {
TrustLevel.PUBLIC,
false
);
Main.executor.scheduleAtFixedRate(() -> ratelimit = 0, 0, 5, TimeUnit.SECONDS);
}
@Override
public Component execute(CommandContext context) throws CommandException {
ratelimit++;
if (ratelimit > 10) return null;
if (context.bot.music.locked) throw new CommandException(Component.text("Managing music is currently locked"));
final String action = context.getString(false, true, true);
@ -264,7 +257,7 @@ public class MusicCommand extends Command {
final CompletableFuture<Component> future = bot.core.runTracked(
"minecraft:data get entity " +
UUIDUtilities.selector(context.sender.profile.getId()) +
" SelectedItem.tag.SongItemData.SongData"
" SelectedItem.components.minecraft:custom_data.SongItemData.SongData"
);
if (future == null) {
@ -281,7 +274,7 @@ public class MusicCommand extends Command {
.key()
.equals("arguments.nbtpath.nothing_found")
) {
context.sendOutput(Component.text("Player has no SongItemData -> SongData NBT tag in the selected item").color(NamedTextColor.RED));
context.sendOutput(Component.text("Player has no SongItemData -> SongData NBT tag in their selected item's minecraft:custom_data").color(NamedTextColor.RED));
return output;
}

View file

@ -24,7 +24,11 @@ public class ValidateCommand extends Command {
public Component execute(CommandContext context) throws CommandException {
final Bot bot = context.bot;
final String hash = context.fullArgs[0];
final String[] fullArgs = context.fullArgs;
if (fullArgs.length == 0) return null;
final String hash = fullArgs[0];
if (bot.hashing.isCorrectHash(hash, context.userInputCommandName, context.sender)) return Component.text("Valid hash").color(NamedTextColor.GREEN);
else if (bot.hashing.isCorrectOwnerHash(hash, context.userInputCommandName, context.sender)) return Component.text("Valid OwnerHash").color(NamedTextColor.GREEN);

View file

@ -57,18 +57,18 @@ public class WhitelistCommand extends Command {
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
}
case "remove" -> {
final String player = context.getString(true, true);
try {
final int index = context.getInteger(true);
if (!bot.whitelist.list.contains(player)) throw new CommandException(Component.text("Player doesn't exist in the list"));
final String player = bot.whitelist.remove(index);
if (player.equals(bot.profile.getName())) throw new CommandException(Component.text("Cannot remove the bot"));
bot.whitelist.remove(player);
return Component.translatable(
"Removed %s from the whitelist",
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
return Component.translatable(
"Removed %s from the whitelist",
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
throw new CommandException(Component.text("Invalid index"));
}
}
case "clear" -> {
context.checkOverloadArgs(1);

View file

@ -15,7 +15,7 @@ public class EvalFunction {
this.bot = bot;
}
public Output execute (Object ...args) { return null; }
public Output execute (Object ...args) throws Exception { return null; }
public static class Output {
public final String message;

View file

@ -10,6 +10,8 @@ public class ChatFunction extends EvalFunction {
@Override
public Output execute(Object... args) {
if (args.length == 0) return null;
final String message = (String) args[0];
bot.chat.send(message);

View file

@ -2,6 +2,11 @@ package me.chayapak1.chomens_bot.evalFunctions;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class CoreFunction extends EvalFunction {
public CoreFunction (Bot bot) {
@ -9,11 +14,13 @@ public class CoreFunction extends EvalFunction {
}
@Override
public Output execute(Object... args) {
public Output execute(Object... args) throws Exception {
if (args.length == 0) return null;
final String command = (String) args[0];
bot.core.run(command);
final CompletableFuture<Component> future = bot.core.runTracked(command);
return null;
return new Output(GsonComponentSerializer.gson().serialize(future.get(1, TimeUnit.SECONDS)), true);
}
}

View file

@ -10,6 +10,8 @@ public class CorePlaceBlockFunction extends EvalFunction {
@Override
public Output execute(Object... args) {
if (args.length == 0) return null;
final String command = (String) args[0];
bot.core.runPlaceBlock(command);

View file

@ -0,0 +1,23 @@
package me.chayapak1.chomens_bot.evalFunctions;
import com.google.gson.JsonObject;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
public class GetBotInfoFunction extends EvalFunction {
public GetBotInfoFunction(Bot bot) {
super("getBotInfo", bot);
}
@Override
public Output execute(Object... args) {
final JsonObject object = new JsonObject();
object.addProperty("usernane", bot.username);
object.addProperty("host", bot.host);
object.addProperty("port", bot.port);
object.addProperty("loggedIn", bot.loggedIn);
return new Output(object.toString(), true);
}
}

View file

@ -0,0 +1,33 @@
package me.chayapak1.chomens_bot.evalFunctions;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
import me.chayapak1.chomens_bot.plugins.ChatPlugin;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class GetLatestChatMessageFunction extends EvalFunction {
private String latestMessage = "";
public GetLatestChatMessageFunction (Bot bot) {
super("getLatestChatMessage", bot);
bot.chat.addListener(new ChatPlugin.Listener() {
@Override
public boolean systemMessageReceived(Component component, String string, String ansi) {
messageReceived(component);
return true;
}
});
}
private void messageReceived (Component component) {
latestMessage = GsonComponentSerializer.gson().serialize(component);
}
@Override
public Output execute(Object... args) {
return new Output(latestMessage, true);
}
}

View file

@ -23,6 +23,8 @@ public class AuthPlugin extends PlayersPlugin.Listener {
private boolean hasCorrectHash;
private PlayerEntry targetPlayer;
private boolean started = false;
public AuthPlugin (Bot bot) {
@ -39,7 +41,7 @@ public class AuthPlugin extends PlayersPlugin.Listener {
return AuthPlugin.this.systemMessageReceived(component);
}
});
bot.executor.scheduleAtFixedRate(this::check, 0, 1, TimeUnit.SECONDS);
bot.executor.scheduleAtFixedRate(this::check, 1, 3, TimeUnit.SECONDS);
}
private String getSanitizedOwnerName() {
@ -50,6 +52,8 @@ public class AuthPlugin extends PlayersPlugin.Listener {
public void playerJoined(PlayerEntry target) {
if (!target.profile.getName().equals(getSanitizedOwnerName()) || !bot.options.useCore) return;
targetPlayer = target;
bot.executor.schedule(() -> sendVerificationMessage(target, true), 2, TimeUnit.SECONDS);
}
@ -110,6 +114,8 @@ public class AuthPlugin extends PlayersPlugin.Listener {
hasCorrectHash = inputHash.equals(hash);
if (hasCorrectHash && targetPlayer != null) bot.chat.tellraw(Component.text("You have been verified").color(NamedTextColor.GREEN), targetPlayer.profile.getId());
return false;
} catch (Exception ignored) {}
@ -117,7 +123,7 @@ public class AuthPlugin extends PlayersPlugin.Listener {
}
private void check() {
if (!started) return;
if (!started || !bot.config.ownerAuthentication.enabled) return;
final PlayerEntry entry = bot.players.getEntry(getSanitizedOwnerName());

View file

@ -26,14 +26,14 @@ public class CloopPlugin {
loopTasks.add(bot.executor.scheduleAtFixedRate(loopTask, 0, interval, TimeUnit.MILLISECONDS));
}
public void remove (int index) {
public CommandLoop remove (int index) {
ScheduledFuture<?> loopTask = loopTasks.remove(index);
if (loopTask != null) {
loopTask.cancel(true);
}
loops.remove(index);
return loops.remove(index);
}
public void clear () {

View file

@ -94,6 +94,8 @@ public class CommandHandlerPlugin {
final String[] splitInput = input.trim().split("\\s+");
if (splitInput.length == 0) return null;
final String commandName = splitInput[0];
final Command command = findCommand(commands, commandName);

View file

@ -374,6 +374,8 @@ public class CorePlugin extends PositionPlugin.Listener {
@Override
public void positionChange (Vector3i position) {
if (bot.position.isGoingDownFromHeightLimit) return;
from = Vector3i.from(
(int) (fromSize.getX() + Math.floor((double) bot.position.position.getX() / 16) * 16),
MathUtilities.clamp(fromSize.getY(), bot.world.minY, bot.world.maxY),

View file

@ -7,10 +7,7 @@ import io.socket.client.Socket;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
import me.chayapak1.chomens_bot.data.eval.EvalOutput;
import me.chayapak1.chomens_bot.evalFunctions.ChatFunction;
import me.chayapak1.chomens_bot.evalFunctions.CoreFunction;
import me.chayapak1.chomens_bot.evalFunctions.CorePlaceBlockFunction;
import me.chayapak1.chomens_bot.evalFunctions.GetPlayerListFunction;
import me.chayapak1.chomens_bot.evalFunctions.*;
import java.util.ArrayList;
import java.util.HashMap;
@ -38,6 +35,8 @@ public class EvalPlugin {
functions.add(new CorePlaceBlockFunction(bot));
functions.add(new ChatFunction(bot));
functions.add(new GetPlayerListFunction(bot));
functions.add(new GetBotInfoFunction(bot));
functions.add(new GetLatestChatMessageFunction(bot));
try {
socket = IO.socket(bot.config.eval.address);
@ -61,16 +60,20 @@ public class EvalPlugin {
socket.on(Socket.EVENT_CONNECT_ERROR, (args) -> connected = false);
for (EvalFunction function : functions) {
socket.on(BRIDGE_PREFIX + function.name, args -> {
final EvalFunction.Output output = function.execute(args);
socket.on(BRIDGE_PREFIX + function.name, args -> new Thread(() -> {
try {
final EvalFunction.Output output = function.execute(args);
if (output == null) return;
if (output == null) return;
socket.emit("functionOutput:" + function.name, output.message, output.parseJSON);
});
socket.emit("functionOutput:" + function.name, output.message, output.parseJSON);
} catch (Exception ignored) {}
}).start());
}
socket.on("codeOutput", (args) -> {
if (args.length < 3) return;
final int id = (int) args[0];
final boolean isError = (boolean) args[1];
final String output = (String) args[2];

View file

@ -18,6 +18,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.regex.Pattern;
@ -104,10 +105,12 @@ public class GrepLogPlugin {
.queue(message -> {
final String url = message.getAttachments().get(0).getUrl();
final DecimalFormat formatter = new DecimalFormat("#,###");
final Component component = Component.translatable("Found %s matches for %s. You can see the results by clicking %s or in the Discord server.")
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
.arguments(
Component.text(matches).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
Component.text(formatter.format(matches)).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
Component.text(input).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
Component
.text("here")
@ -126,6 +129,9 @@ public class GrepLogPlugin {
context.sendOutput(component);
});
} catch (CommandException e) {
running = false;
throw e;
} catch (FileNotFoundException e) {
running = false;
throw new CommandException(Component.text("File not found"));

View file

@ -169,7 +169,7 @@ public class IRCPlugin extends ListenerAdapter {
}
public void quit (String reason) {
bot.sendIRC().quitServer(reason);
if (bot.isConnected()) bot.sendIRC().quitServer(reason);
}
private void connected (Bot bot) {
@ -202,9 +202,7 @@ public class IRCPlugin extends ListenerAdapter {
bot.sendIRC().message(entry.getKey(), withIRCColors);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception ignored) {}
}
private void addMessageToQueue (Bot bot, String message) {

View file

@ -56,6 +56,8 @@ public class MusicPlayerPlugin extends Bot.Listener {
private int limit = 0;
public boolean locked = false; // this can be set through servereval
private final String bossbarName = "music";
public BossBarColor bossBarColor;
@ -73,7 +75,7 @@ public class MusicPlayerPlugin extends Bot.Listener {
}
public void loadSong (Path location, PlayerEntry sender) {
if (songQueue.size() > 100) return;
if (songQueue.size() > 500) return;
loaderThread = new SongLoaderThread(location, bot, sender.profile.getName());
@ -90,7 +92,7 @@ public class MusicPlayerPlugin extends Bot.Listener {
}
public void loadSong (URL location, PlayerEntry sender) {
if (songQueue.size() > 100) return;
if (songQueue.size() > 500) return;
limit++;
@ -114,7 +116,7 @@ public class MusicPlayerPlugin extends Bot.Listener {
}
public void loadSong (byte[] data, PlayerEntry sender) {
if (songQueue.size() > 100) return;
if (songQueue.size() > 500) return;
loaderThread = new SongLoaderThread(data, bot, sender.profile.getName());
@ -194,13 +196,9 @@ public class MusicPlayerPlugin extends Bot.Listener {
if (songQueue.isEmpty()) {
stopPlaying();
removeBossBar();
bot.chat.tellraw(
Component
.text("Finished playing every song in the queue")
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
);
return;
}
if (currentSong.size() > 0) {
currentSong = songQueue.get(0);
currentSong.setTime(0);

View file

@ -30,6 +30,8 @@ public class PositionPlugin extends Bot.Listener {
public Vector3i position = Vector3i.from(0, 0, 0);
public boolean isGoingDownFromHeightLimit = false; // cool variable name
private final Map<Integer, PlayerEntry> entityIdMap = new HashMap<>();
private final Map<Integer, Vector3f> positionMap = new HashMap<>();
private final Map<Integer, Rotation> rotationMap = new HashMap<>();
@ -40,12 +42,23 @@ public class PositionPlugin extends Bot.Listener {
bot.addListener(this);
// notchian clients also does this, sends the position packet every second
bot.executor.scheduleAtFixedRate(() -> bot.session.send(new ServerboundMovePlayerPosPacket(
false,
position.getX(),
position.getY(),
position.getZ()
)), 0, 1, TimeUnit.SECONDS);
bot.executor.scheduleAtFixedRate(() -> {
if (isGoingDownFromHeightLimit) return;
bot.session.send(new ServerboundMovePlayerPosPacket(
false,
position.getX(),
position.getY(),
position.getZ()
));
}, 0, 1, TimeUnit.SECONDS);
bot.tick.addListener(new TickPlugin.Listener() {
@Override
public void onTick() {
handleHeightLimit();
}
});
}
@Override
@ -145,6 +158,52 @@ public class PositionPlugin extends Bot.Listener {
for (Listener listener : listeners) listener.playerMoved(player, position, rotation);
}
// for now this is used in CorePlugin when placing the command block
private void handleHeightLimit () {
final int y = position.getY();
final int minY = bot.world.minY;
final int maxY = bot.world.maxY;
if (y < maxY) {
if (isGoingDownFromHeightLimit) {
isGoingDownFromHeightLimit = false;
for (Listener listener : listeners) { listener.positionChange(position); }
}
return;
}
isGoingDownFromHeightLimit = true;
final Vector3i newPosition = Vector3i.from(
position.getX(),
position.getY() - 2,
position.getZ()
);
position = newPosition;
if (position.getY() > maxY + 500 || position.getY() < minY) {
String command = "/";
if (bot.serverPluginsManager.hasPlugin(ServerPluginsManagerPlugin.ESSENTIALS)) command += "essentials:";
command += String.format("tp ~ %s ~", maxY - 1);
bot.chat.send(command);
return;
}
bot.session.send(new ServerboundMovePlayerPosPacket(
false,
newPosition.getX(),
newPosition.getY(),
newPosition.getZ()
));
}
public Vector3f getPlayerPosition (String playerName) {
int entityId = -1;
for (Map.Entry<Integer, PlayerEntry> entry : entityIdMap.entrySet()) {

View file

@ -58,7 +58,7 @@ public class VoiceChatPlugin extends Bot.Listener {
bot.session.send(new ServerboundCustomPayloadPacket(
Key.key("voicechat:request_secret"),
new FriendlyByteBuf(Unpooled.buffer()).writeInt(17).array()
new FriendlyByteBuf(Unpooled.buffer()).writeInt(18).array()
));
bot.session.send(new ServerboundCustomPayloadPacket(

View file

@ -51,13 +51,7 @@ public class WhitelistPlugin extends PlayersPlugin.Listener {
}
public void add (String player) { list.add(player); }
public void remove (String player) {
list.removeIf(eachPlayer -> eachPlayer.equals(player));
final PlayerEntry entry = bot.players.getEntry(player);
if (entry != null) handle(entry);
}
public String remove (int index) { return list.remove(index); }
public void clear () {
list.removeIf(eachPlayer -> !eachPlayer.equals(bot.profile.getName()));
}
@ -72,7 +66,7 @@ public class WhitelistPlugin extends PlayersPlugin.Listener {
}
public void commandReceived (PlayerEntry entry, String command) {
if (!enabled || list.contains(entry.profile.getName())) return;
if (!enabled || list.contains(entry.profile.getName()) || entry.profile.equals(bot.profile)) return;
if (
command.startsWith("mute") ||
@ -90,7 +84,7 @@ public class WhitelistPlugin extends PlayersPlugin.Listener {
}
private void handle (PlayerEntry entry) {
if (!enabled || list.contains(entry.profile.getName())) return;
if (!enabled || list.contains(entry.profile.getName()) || entry.profile.equals(bot.profile)) return;
bot.filter.doAll(entry);
}

View file

@ -34,14 +34,17 @@ public class WorldPlugin extends Bot.Listener {
private void worldChanged (String dimension) {
final RegistryEntry currentDimension = registry.stream()
.filter(eachDimension -> eachDimension.getId().asString().equals(dimension))
.toArray(RegistryEntry[]::new)[0];
.findFirst()
.orElse(null);
if (currentDimension == null) return;
final NbtMap data = currentDimension.getData();
if (data == null) return;
minY = data.getInt("min_y");
maxY = data.getInt("height");
maxY = data.getInt("height") + minY;
for (Listener listener : listeners) listener.worldChanged(dimension);
}

View file

@ -215,7 +215,8 @@ public class MidiConverter implements Converter {
shiftedInstrument = Arrays.stream(instrumentList)
.filter(ins -> ins.offset == closest)
.toArray(Instrument[]::new)[0];
.findFirst()
.orElse(null);
}
}

View file

@ -17,7 +17,7 @@ public class Song {
public long startTime = 0; // Start time in millis since unix epoch
public long length = 0; // Milliseconds in the song
public long time = 0; // Time since start of song
public long loopPosition = 200; // Milliseconds into the song to start looping
public long loopPosition = 0; // Milliseconds into the song to start looping
public final Map<Long, String> lyrics = new HashMap<>();
@ -80,7 +80,7 @@ public class Song {
*/
public void play () {
if (paused) {
if (loopPosition != 200) bot.music.loop = Loop.CURRENT;
if (loopPosition != 0) bot.music.loop = Loop.CURRENT;
paused = false;
startTime = System.currentTimeMillis() - time;
}

View file

@ -46,7 +46,7 @@ public class SongPlayerConverter implements Converter {
song.length = songLength;
// song.looping = loop > 0;
// song.loopCount = loopCount;
song.loopPosition = loopPosition == 0 ? 200 : loopPosition;
song.loopPosition = loopPosition;
long time = 0;
while (true) {

View file

@ -259,7 +259,7 @@ public class ComponentUtilities {
}
// messy af
return new PartiallyStringified((lastColor != null ? lastColor : "") + (color != null ? color : "") + (style != null ? style : "") + replacedContent + (ansi ? ansiMap.get("r") : ""), color);
return new PartiallyStringified((lastColor != null ? lastColor : "") + (color != null ? color : "") + (style != null ? style : "") + replacedContent + (ansi ? ansiMap.get("r") : "") + (style != null ? style : ""), color);
}
return new PartiallyStringified(message.content(), null);
@ -280,6 +280,8 @@ public class ComponentUtilities {
int i = 0;
while (matcher.find()) {
if (i > 300) break;
if (matcher.group().equals("%%")) {
matcher.appendReplacement(sb, "%");
} else {
@ -305,7 +307,7 @@ public class ComponentUtilities {
}
matcher.appendTail(sb);
return new PartiallyStringified((lastColor != null ? lastColor : "") + color + (style != null && ansi ? style : "") + sb + (ansi ? ansiMap.get("r") : ""), _color);
return new PartiallyStringified((lastColor != null ? lastColor : "") + color + (style != null && ansi ? style : "") + sb + (ansi ? ansiMap.get("r") + (style != null ? style : "") : ""), _color);
}
public static PartiallyStringified stringifyPartially (SelectorComponent message, boolean motd, boolean ansi, String lastColor, boolean noHex) {

View file

@ -2,10 +2,7 @@ package me.chayapak1.chomens_bot.util;
import me.chayapak1.chomens_bot.Main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@ -18,12 +15,13 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPOutputStream;
// totallynotskidded from HBot
// original source code from hhhzzzsss, specifically HBot.
// source: https://github.com/hhhzzzsss/HBot-Release/blob/main/src/main/java/com/github/hhhzzzsss/hbot/Logger.java
public class FileLoggerUtilities {
public static final Path logDirectory = Path.of("logs");
public static final Path logPath = Paths.get(logDirectory.toString(), "log.txt");
public static BufferedWriter logWriter;
public static OutputStreamWriter logWriter;
public static LocalDate currentLogDate;
public static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("'['dd/MM/yyyy HH:mm:ss']' ");
@ -79,56 +77,49 @@ public class FileLoggerUtilities {
}
}
public static void makeNewLogFile() throws IOException {
public static synchronized void makeNewLogFile() throws IOException {
currentLogDate = LocalDate.now();
if (!Files.exists(logPath)) Files.createFile(logPath);
logWriter = Files.newBufferedWriter(logPath, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING);
logWriter = new OutputStreamWriter(Files.newOutputStream(logPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING), StandardCharsets.UTF_8);
logWriter.write(currentLogDate.toString() + '\n');
logWriter.flush();
}
public static void openLogFile() throws IOException {
public static synchronized void openLogFile() throws IOException {
currentLogDate = LocalDate.parse(getLogDate(logPath));
logWriter = Files.newBufferedWriter(logPath, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
logWriter = new OutputStreamWriter(Files.newOutputStream(logPath, StandardOpenOption.CREATE, StandardOpenOption.APPEND), StandardCharsets.UTF_8);
}
public static void compressLogFile() throws IOException {
public static synchronized void compressLogFile() throws IOException {
if (Files.size(logPath) > 100 * 1024 * 1024) { // Will not save because log file is too big
return;
}
final Path path = Paths.get(logDirectory.toString(), getLogDate(logPath) + ".txt.gz");
Files.createFile(path);
InputStream in = Files.newInputStream(logPath);
GZIPOutputStream out = new GZIPOutputStream(Files.newOutputStream(path));
byte[] buffer = new byte[1024];
int size;
while ((size = in.read(buffer)) > 0) {
out.write(buffer, 0, size);
try (
final InputStream in = Files.newInputStream(logPath, StandardOpenOption.READ);
final GZIPOutputStream out = new GZIPOutputStream(Files.newOutputStream(path, StandardOpenOption.CREATE))
) {
byte[] buffer = new byte[1024];
int size;
while ((size = in.read(buffer)) > 0) {
out.write(buffer, 0, size);
}
}
in.close();
out.finish();
out.close();
}
public static String getLogDate(Path path) throws IOException {
BufferedReader reader = Files.newBufferedReader(path);
String date = reader.readLine();
reader.close();
return date;
public static synchronized String getLogDate (Path filePath) throws IOException {
try (final BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) {
return reader.readLine();
}
}
public static boolean logIsCurrent(Path path) throws IOException {
public static synchronized boolean logIsCurrent(Path path) throws IOException {
LocalDate date = LocalDate.now();
return getLogDate(path).equals(date.toString());
}
public static void log(String str) {
public static synchronized void log(String str) {
if (freezeTime > System.currentTimeMillis()) {
return;
}
@ -162,8 +153,7 @@ public class FileLoggerUtilities {
logWriter.write("\n");
}
if (str.length() > 32767) logWriter.write("Message too big, not logging this message"); // should these stuff be hardcoded?
else logWriter.write(getTimePrefix() + str.replaceAll("\\[(\\d+?)x](?=$|[\r\n])", "[/$1x]")); // the replaceAll will prevent conflicts with the duplicate counter
logWriter.write(getTimePrefix() + str.replaceAll("\\[(\\d+?)x](?=$|[\r\n])", "[/$1x]")); // the replaceAll will prevent conflicts with the duplicate counter
logWriter.flush();
duplicateCounter = 1;

View file

@ -4,7 +4,6 @@ import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import me.chayapak1.chomens_bot.Main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -12,10 +11,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class PersistentDataUtilities {
public static final Path path = Path.of("persistent.json");
@ -24,33 +19,10 @@ public class PersistentDataUtilities {
public static JsonObject jsonObject = new JsonObject();
private static final Map<String, JsonElement> queue = new ConcurrentHashMap<>();
private static final ScheduledFuture<?> future;
private static boolean stopping = false;
static {
init();
future = Main.executor.scheduleAtFixedRate(() -> {
try {
if (queue.isEmpty()) return;
final Map.Entry<String, JsonElement> entry = queue.entrySet().iterator().next(); // is this the best way to get the first item of the map?
final String property = entry.getKey();
final JsonElement value = entry.getValue();
Main.executorService.submit(() -> {
jsonObject.add(property, value);
write(jsonObject.toString());
queue.remove(property);
});
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 100, TimeUnit.MILLISECONDS);
}
private static void init () {
@ -66,19 +38,17 @@ public class PersistentDataUtilities {
jsonObject = gson.fromJson(reader, JsonObject.class);
}
writer = Files.newBufferedWriter(path, StandardOpenOption.TRUNCATE_EXISTING);
writer = Files.newBufferedWriter(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void write (String string) {
try {
writer.close();
if (stopping) return; // is this necessary?
// ? how do i clear the file contents without making a completely new writer?
// or is this the only way?
writer = Files.newBufferedWriter(path, StandardOpenOption.TRUNCATE_EXISTING);
try {
writer = Files.newBufferedWriter(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
writer.write(string);
writer.flush();
@ -86,27 +56,32 @@ public class PersistentDataUtilities {
}
public static void stop () {
future.cancel(false);
stopping = true;
write(jsonObject.toString());
}
public static void put (String property, JsonElement value) {
Main.executorService.submit(() -> queue.put(property, value));
jsonObject.add(property, value);
write(jsonObject.toString());
}
public static void put (String property, String value) {
Main.executorService.submit(() -> queue.put(property, new JsonPrimitive(value)));
jsonObject.add(property, new JsonPrimitive(value));
write(jsonObject.toString());
}
public static void put (String property, boolean value) {
Main.executorService.submit(() -> queue.put(property, new JsonPrimitive(value)));
jsonObject.add(property, new JsonPrimitive(value));
write(jsonObject.toString());
}
public static void put (String property, int value) {
Main.executorService.submit(() -> queue.put(property, new JsonPrimitive(value)));
jsonObject.add(property, new JsonPrimitive(value));
write(jsonObject.toString());
}
public static void put (String property, char value) {
Main.executorService.submit(() -> queue.put(property, new JsonPrimitive(value)));
jsonObject.add(property, new JsonPrimitive(value));
write(jsonObject.toString());
}
}

View file

@ -16,7 +16,7 @@ internetCheck:
# how backup works is that it checks for the address every 1 minute,
# if the address is reachable it will not start the bot
# if the address is not reachable then it will start the bot
#
# if the bot has already been started and the address is back up it
# will stop the bot (using System.exit(1))
backup:
@ -59,7 +59,8 @@ colorPalette:
number: 'gold'
ownerName: 'green'
ownerName: 'chayapak' # currently this is only used in the console
# you HAVE TO CHANGE THIS if you are hosting another instance of my bot.
ownerName: 'XxChange_mexX'
imposterFormatChecker:
enabled: false