diff --git a/src/main/java/org/pearlbot/PearlBotMessages.java b/src/main/java/org/pearlbot/PearlBotMessages.java new file mode 100644 index 0000000..0977336 --- /dev/null +++ b/src/main/java/org/pearlbot/PearlBotMessages.java @@ -0,0 +1,71 @@ +/* + * PearlBot — a ZenithProxy plugin for on-demand stasis chamber pulls. + * Copyright (C) 2026 Leonetic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.pearlbot; + +public class PearlBotMessages { + + // --- In-game whispers --- + + public String noPearlFound = "No pearl found for you."; + + // {remaining} = e.g. "2 pearls" or "1 pearl" + public String pulled = "Pulled. You have {remaining} left."; + + // {count} = current pearl count, {max} = configured max + public String maxPearlsExceeded = "You have {count} pearl(s) but the max is {max}! Automatically pulling your oldest pearl."; + + // {count} = e.g. "2" or "2/3" when a max is set + public String pearlCount = "You have {count} pearl(s) stasised."; + + // {timeout} = seconds configured for pull timeout + public String pullTimedOut = "Positioning timed out after {timeout}s."; + + // {timeout} = seconds configured for owner-online timeout + public String ownerTimedOut = "Expired - you did not log on within {timeout}s."; + + public String authUsage = "Usage: !auth - get a code by typing !auth in Discord first."; + public String authInvalidCode = "Invalid or expired code."; + + // {discordUsername} = the Discord username that was linked + public String authLinked = "Linked to Discord {discordUsername}."; + + // --- Discord messages (the @mention is prepended automatically) --- + + public String discordNoAccountsLinked = "No MC accounts linked. Type `!auth` to link one."; + + // {accounts} = comma-separated account names, {trigger} = e.g. "!warp" + public String discordMultipleAccounts = "Accounts linked: {accounts}. Please type `{trigger} ` to pull a specific account."; + + // {name} = the username that wasn't found, {accounts} = comma-separated linked account names + public String discordAccountNotFound = "No linked account named `{name}`. Accounts linked: {accounts}."; + + // {code} = auth code, {ttl} = minutes until expiry + public String discordAuthCode = "Whisper me `!auth {code}` in-game from each MC account you want to link. Expires in {ttl} minutes."; + + // {mcUsername} = the MC account that was linked + public String discordAuthLinked = "Linked MC account `{mcUsername}`."; + + // Replaces {key} placeholders — pass alternating key, value pairs + public String format(String template, Object... keyValues) { + String result = template; + for (int i = 0; i + 1 < keyValues.length; i += 2) { + result = result.replace("{" + keyValues[i] + "}", String.valueOf(keyValues[i + 1])); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/org/pearlbot/PearlBotPlugin.java b/src/main/java/org/pearlbot/PearlBotPlugin.java index ad3dcdb..e06ef17 100644 --- a/src/main/java/org/pearlbot/PearlBotPlugin.java +++ b/src/main/java/org/pearlbot/PearlBotPlugin.java @@ -36,6 +36,7 @@ public class PearlBotPlugin implements ZenithProxyPlugin { public static PluginAPI API; public static PearlBotConfig PLUGIN_CONFIG; + public static PearlBotMessages PLUGIN_MESSAGES; public static ComponentLogger LOG; @Override @@ -44,6 +45,7 @@ public void onLoad(PluginAPI pluginAPI) { LOG = pluginAPI.getLogger(); LOG.info("PearlBot loading..."); PLUGIN_CONFIG = API.registerConfig(BuildConstants.PLUGIN_ID, PearlBotConfig.class); + PLUGIN_MESSAGES = API.registerConfig(BuildConstants.PLUGIN_ID + "-messages", PearlBotMessages.class); API.registerModule(new EnderPearlTrackerModule()); API.registerModule(new AutoPearlModule()); API.registerCommand(new PearlBotCommand()); diff --git a/src/main/java/org/pearlbot/module/AutoPearlModule.java b/src/main/java/org/pearlbot/module/AutoPearlModule.java index 8fff82f..d6f1103 100644 --- a/src/main/java/org/pearlbot/module/AutoPearlModule.java +++ b/src/main/java/org/pearlbot/module/AutoPearlModule.java @@ -46,6 +46,7 @@ import static com.zenith.Globals.CONFIG; import static com.zenith.Globals.DISCORD; import static org.pearlbot.PearlBotPlugin.PLUGIN_CONFIG; +import static org.pearlbot.PearlBotPlugin.PLUGIN_MESSAGES; public class AutoPearlModule extends Module { private static final long PULL_RETRY_INTERVAL_MS = 1_000L; @@ -138,7 +139,7 @@ private void onWhisper(WhisperChatEvent event) { .count(); int max = PLUGIN_CONFIG.maxChambersPerPlayer; String countStr = max > 0 ? count + "/" + max : String.valueOf(count); - sendWhisper(name, "You have " + countStr + " pearl(s) set."); + sendWhisper(name, PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.pearlCount, "count", countStr)); return; } @@ -150,7 +151,7 @@ private void onWhisper(WhisperChatEvent event) { PearlBotConfig.StasisChamber chamber = findChamberFor(uuid); if (chamber == null) { - sendWhisper(name, "No pearl found for you."); + sendWhisper(name, PLUGIN_MESSAGES.noPearlFound); return; } @@ -159,19 +160,19 @@ private void onWhisper(WhisperChatEvent event) { private void handleAuthWhisper(UUID mcUuid, String mcUsername, String code) { if (code.isBlank()) { - sendWhisper(mcUsername, "Usage: !auth - get a code with !auth in Discord first."); + sendWhisper(mcUsername, PLUGIN_MESSAGES.authUsage); return; } purgeExpiredAuthCodes(); PendingAuth pending = pendingAuthCodes.remove(code.toUpperCase()); if (pending == null) { - sendWhisper(mcUsername, "Invalid or expired code."); + sendWhisper(mcUsername, PLUGIN_MESSAGES.authInvalidCode); return; } PLUGIN_CONFIG.linkedAccounts.put(mcUuid, new PearlBotConfig.LinkedAccount( pending.discordUserId, pending.discordUsername, mcUsername, System.currentTimeMillis())); info("Linked MC {} ({}) to Discord {} ({})", mcUsername, mcUuid, pending.discordUsername, pending.discordUserId); - sendWhisper(mcUsername, "Linked to Discord " + pending.discordUsername + "."); + sendWhisper(mcUsername, PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.authLinked, "discordUsername", pending.discordUsername)); notifyAuthSuccess(pending.discordUserId, mcUsername); } @@ -184,7 +185,7 @@ private void notifyAuthSuccess(String discordUserId, String mcUsername) { warn("Cannot send auth-success ping: channel {} not found", channelId); return; } - channel.sendMessage("<@" + discordUserId + "> Linked MC account `" + mcUsername + "`.").queue(); + channel.sendMessage("<@" + discordUserId + "> " + PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.discordAuthLinked, "mcUsername", mcUsername)).queue(); } private void onDiscordMessage(MessageReceivedEvent jdaEvent) { @@ -205,8 +206,7 @@ private void onDiscordMessage(MessageReceivedEvent jdaEvent) { if (firstWord.equals(DISCORD_AUTH_CMD)) { String code = newAuthCode(discordUserId, discordUsername); long ttl = (long) PLUGIN_CONFIG.discordTrigger.authCodeTtlMinutes; - channel.sendMessage("<@" + discordUserId + "> Whisper me `!auth " + code - + "` in-game from each MC account you want to link. Expires in " + ttl + " minutes.").queue(); + channel.sendMessage("<@" + discordUserId + "> " + PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.discordAuthCode, "code", code, "ttl", ttl)).queue(); return; } @@ -221,7 +221,7 @@ private void onDiscordMessage(MessageReceivedEvent jdaEvent) { .map(Map.Entry::getValue) .toList(); if (linked.isEmpty()) { - channel.sendMessage("<@" + discordUserId + "> No MC accounts linked. Type `!auth` to link one.").queue(); + channel.sendMessage("<@" + discordUserId + "> " + PLUGIN_MESSAGES.discordNoAccountsLinked).queue(); return; } @@ -229,8 +229,7 @@ private void onDiscordMessage(MessageReceivedEvent jdaEvent) { String names = linked.stream() .map(a -> a.mcUsername != null ? a.mcUsername : "?") .collect(java.util.stream.Collectors.joining(", ")); - channel.sendMessage("<@" + discordUserId + "> Accounts linked: " + names - + ". Please type `" + triggerWordDiscord() + " ` to pull a specific account.").queue(); + channel.sendMessage("<@" + discordUserId + "> " + PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.discordMultipleAccounts, "accounts", names, "trigger", triggerWordDiscord())).queue(); return; } @@ -258,8 +257,7 @@ private void onDiscordMessage(MessageReceivedEvent jdaEvent) { String names = linked.stream() .map(a -> a.mcUsername != null ? a.mcUsername : "?") .collect(java.util.stream.Collectors.joining(", ")); - channel.sendMessage("<@" + discordUserId + "> No linked account named `" + targetName - + "`. Accounts linked: " + names + ".").queue(); + channel.sendMessage("<@" + discordUserId + "> " + PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.discordAccountNotFound, "name", targetName, "accounts", names)).queue(); return; } @@ -326,8 +324,7 @@ public void checkAndEnforceMaxChambers(UUID ownerUuid) { PearlBotConfig.StasisChamber chamber = findChamberFor(ownerUuid); if (chamber == null) return; if (name != null) { - sendWhisper(name, "You have " + count + " pearl(s) but the max is " + max - + "! Pulling your oldest pearl."); + sendWhisper(name, PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.maxPearlsExceeded, "count", count, "max", max)); } enqueuePull(ownerUuid, name, chamber); } @@ -387,7 +384,7 @@ private void tickPending() { if (timeoutMs > 0 && now - activePullStartMs > timeoutMs) { warn("Positioning for {} timed out after {}s; cancelling", labelOf(activePull), PLUGIN_CONFIG.pullTimeoutSeconds); - abortActivePull("Positioning timed out after " + PLUGIN_CONFIG.pullTimeoutSeconds + "s."); + abortActivePull(PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.pullTimedOut, "timeout", PLUGIN_CONFIG.pullTimeoutSeconds)); return; } } else if (isOwnerOnline(activePull.ownerUuid)) { @@ -397,8 +394,7 @@ private void tickPending() { if (waitMs > 0 && now - readyAtMs > waitMs) { warn("{} did not come online within {}s; expiring pull", labelOf(activePull), PLUGIN_CONFIG.waitForOwnerSeconds); - abortActivePull("Expired - you did not log on within " - + PLUGIN_CONFIG.waitForOwnerSeconds + "s."); + abortActivePull(PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.ownerTimedOut, "timeout", PLUGIN_CONFIG.waitForOwnerSeconds)); return; } } @@ -540,7 +536,7 @@ private void fireClick() { int remaining = Math.max(0, remainingPearlsFor(pull.ownerUuid) - 1); if (pull.ownerName != null) { String tail = remaining == 1 ? "1 pearl" : remaining + " pearls"; - sendWhisper(pull.ownerName, "Pulled. You have " + tail + " left."); + sendWhisper(pull.ownerName, PLUGIN_MESSAGES.format(PLUGIN_MESSAGES.pulled, "remaining", tail)); } if (PLUGIN_CONFIG.idleGoal.enabled) {