diff --git a/README.md b/README.md index 3f18c19..4fbf2f2 100644 --- a/README.md +++ b/README.md @@ -99,14 +99,8 @@ Quickly kills (terminates) the server on trigger, via command or HTTP request. Self-explanatory ### Durability alert -Self-explanatory too. - -`/durabilityalert` (`tweaks724.durabilityalert`) - -### Word coords -Convert coordinates to easier to remember words - -`/wordcoords` (`tweaks724.tauth`) +Self-explanatory too. \ +For simplicity, there's no configuration. Control with `tweaks724.durabilityalert` ### Utility commands diff --git a/pom.xml b/pom.xml index 7c04e18..22761da 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.15-SNAPSHOT + 0.1.14 21 @@ -147,7 +147,7 @@ eu.m724 mstats-spigot - 0.1.2 + 0.1.0 provided @@ -168,6 +168,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.14 \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 82adee7..7da3a4a 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -27,7 +27,6 @@ import eu.m724.tweaks.module.redstone.RedstoneModule; import eu.m724.tweaks.module.sleep.SleepModule; import eu.m724.tweaks.module.swing.SwingModule; import eu.m724.tweaks.module.updater.UpdaterModule; -import eu.m724.tweaks.module.wordcoords.WordCoordsModule; import eu.m724.tweaks.module.worldborder.WorldBorderExpandModule; import eu.m724.tweaks.module.worldborder.WorldBorderHideModule; @@ -158,8 +157,6 @@ public class TweaksPlugin extends MStatsPlugin { TweaksModule.init(DurabilityModule.class); - TweaksModule.init(WordCoordsModule.class); - /* end modules */ if (config.metrics()) { @@ -167,7 +164,7 @@ public class TweaksPlugin extends MStatsPlugin { mStats(1); } - DebugLogger.fine("Took %.3f milliseconds", (System.nanoTime() - start) / 1000000.0); + DebugLogger.fine("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); } private String getTargetVersion() { diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java deleted file mode 100644 index 054d1ee..0000000 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2025 Minecon724 - * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file - * in the project root for the full license text. - */ - -package eu.m724.tweaks.module.wordcoords; - -import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.module.wordcoords.converter.Decoder; -import eu.m724.tweaks.module.wordcoords.converter.Encoder; - -import java.util.NoSuchElementException; - -public class WordCoordsConverter { - private final Encoder encoder; - private final Decoder decoder; - - - public WordCoordsConverter(WordList wordList) { - this.encoder = new Encoder(wordList); - this.decoder = new Decoder(wordList); - - DebugLogger.fine("Words: %d (%d bits)", wordList.getWordCount(), wordList.getBitsPerWord()); - DebugLogger.fine("Bits per word: %d", wordList.getBitsPerWord()); - } - - public String[] encode(int x, int z) { - return encoder.encode(x, z); - } - - public int[] decode(String[] words) throws NoSuchElementException { - return decoder.decode(words); - } - -} diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java deleted file mode 100644 index 603b33d..0000000 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2025 Minecon724 - * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file - * in the project root for the full license text. - */ - -package eu.m724.tweaks.module.wordcoords; - -import eu.m724.tweaks.Language; -import eu.m724.tweaks.module.TweaksModule; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.hover.content.Text; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; - -public class WordCoordsModule extends TweaksModule implements CommandExecutor, Listener { - private WordList wordList; - private WordCoordsConverter converter; - - @Override - protected void onInit() { - try { - this.wordList = WordList.fromFile(getPlugin().getDataFolder().toPath().resolve("storage/wordlist.txt")); - } catch (IOException e) { - throw new RuntimeException(e); - } - - this.converter = new WordCoordsConverter(wordList); - - registerCommand("wordcoords", this); - registerEvents(this); - } - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - int x = 0, z = 0; - String[] words = new String[0]; - - boolean encode = false; // means encode pos to words - - if (args.length == 0) { - if (!(sender instanceof Player player)) { - sender.sendMessage(Language.getString("wordCoordsPlayerOnly")); - return true; - } - - x = player.getLocation().getBlockX(); - z = player.getLocation().getBlockZ(); - - encode = true; - } else if (args.length > 1) { - try { - double dx = Double.parseDouble(args[0]); - double dz = Double.parseDouble(args[args.length > 2 ? 2 : 1]); - - if (dx > Integer.MAX_VALUE || dx < Integer.MIN_VALUE || dz > Integer.MAX_VALUE || dz < Integer.MIN_VALUE) { - sender.spigot().sendMessage(Language.getComponent("wordCoordsOutOfRange", ChatColor.RED)); - return true; - } - - x = (int) dx; - z = (int) dz; - - encode = true; - } catch (NumberFormatException ignored) { } - } - - if (encode) { - words = converter.encode(x, z); - String encoded = "///" + String.join(".", words); - - BaseComponent[] components = new ComponentBuilder() - .append(String.format("%d, %d encodes to ", x, z)) - .color(ChatColor.GRAY) - .append(encoded) - .color(ChatColor.AQUA) // TODO improve color - .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, encoded)) - .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to copy"))) - .create(); - - sender.spigot().sendMessage(components); - } else { - String strArgs = String.join(" ", args); - words = smartDetectWords(strArgs); - - if (words.length == 0) { - sender.spigot().sendMessage(Language.getComponent("wordCoordsNoWords", ChatColor.GRAY)); - return true; - } - - try { - int[] xz = converter.decode(words); - x = xz[0]; - z = xz[1]; - } catch (NoSuchElementException e) { - sender.spigot().sendMessage(Language.getComponent("wordCoordsInvalidWord", ChatColor.RED, e.getMessage())); - return true; - } - - String encoded = "///" + String.join(".", words); - - BaseComponent[] components = new ComponentBuilder() - .append(encoded + " decodes to ") - .color(ChatColor.GRAY) - .append("%d, %d".formatted(x, z)) - .color(ChatColor.AQUA) // TODO improve color - .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, "%d, %d".formatted(x, z))) - .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to copy"))) - .append(" ±8") - .color(ChatColor.GRAY) - .create(); - sender.spigot().sendMessage(components); - } - - return true; - } - - private String[] smartDetectWords(String str) { - List words = new ArrayList<>(); - StringBuilder currentWord = new StringBuilder(); - - for (int i=0; i wordList; - private final int bitsPerWord; - - public WordList(List words) { - this.wordList = words; - this.bitsPerWord = 32 - Integer.numberOfLeadingZeros(words.size()) - 1; - } - - public String getWord(int index) { - return wordList.get(index); - } - - public int getWordIndex(String word) { - return wordList.indexOf(word); - } - - public String[] getWords(int... indexes) { - return Arrays.stream(indexes) - .mapToObj(this::getWord) - .toArray(String[]::new); - } - - public int[] getIndexes(String... words) { - return Arrays.stream(words) - .mapToInt(wordList::indexOf) - .toArray(); - } - - public int getWordCount() { - return wordList.size(); - } - - public int getBitsPerWord() { - return bitsPerWord; - } - - public static WordList fromFile(Path path) throws IOException { - try (var lines = Files.lines(path)) { - var list = lines.filter(s -> !s.isBlank()) - .map(String::toLowerCase) - .distinct() - .toList(); - - return new WordList(list); - } - - } -} diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java deleted file mode 100644 index 65ff762..0000000 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2025 Minecon724 - * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file - * in the project root for the full license text. - */ - -package eu.m724.tweaks.module.wordcoords.converter; - -import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.module.wordcoords.WordList; - -import java.util.NoSuchElementException; -import java.util.Arrays; - -public class Decoder { - private final WordList wordList; - private final int bitsPerWord; - - public Decoder(WordList wordList) { - this.wordList = wordList; - this.bitsPerWord = wordList.getBitsPerWord(); - } - - public int[] decode(String[] words) throws NoSuchElementException { - int[] wordIndexes = new int[words.length]; - - for (int i=0; i> bitsRequiredPerCoordinate) - coordinateOffset; - - return new int[] { x, z }; - } - -} diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java deleted file mode 100644 index 75d03e2..0000000 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2025 Minecon724 - * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file - * in the project root for the full license text. - */ - -package eu.m724.tweaks.module.wordcoords.converter; - -import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.module.wordcoords.WordList; -import java.util.Arrays; -public class Encoder { - private final WordList wordList; - private final int bitsPerWord; - - public Encoder(WordList wordList) { - this.wordList = wordList; - this.bitsPerWord = wordList.getBitsPerWord(); - } - - public String[] encode(int xCoord, int zCoord) { - int chunkX = Math.floorDiv(xCoord, 16); - int chunkZ = Math.floorDiv(zCoord, 16); - DebugLogger.finer("Chunk: %d, %d", chunkX, chunkZ); - - // Calculate minimum bits required per coordinate based on range - int bitsRequiredPerCoordinate = findBitsRequiredPerCoordinate(chunkX, chunkZ); - int minTotalBits = bitsRequiredPerCoordinate * 2; - DebugLogger.finer("Min bits required per coordinate: %d (total: %d)", bitsRequiredPerCoordinate, minTotalBits); - - // Calculate words required, ensuring total bits is sufficient and even - int wordsRequired = 0; - int actualTotalBits = 0; - if (minTotalBits > 0) { // Avoid division by zero if bitsPerWord is 0, or log(0) - wordsRequired = Math.ceilDiv(minTotalBits, bitsPerWord); - actualTotalBits = wordsRequired * bitsPerWord; - // Ensure total bits is sufficient - while (actualTotalBits < minTotalBits) { - wordsRequired++; - actualTotalBits = wordsRequired * bitsPerWord; - } - } // else: coords are 0 or -1, minTotalBits=0, wordsRequired=0, actualTotalBits=0. Need special handling? - // If x/z are 0/-1, findBitsRequired returns 1, minTotalBits=2. The loop handles it. - - // Final bits per coordinate based on words - bitsRequiredPerCoordinate = actualTotalBits / 2; - DebugLogger.finer("Final Words required: %d", wordsRequired); - DebugLogger.finer("Final Bits required: %d (per coord: %d)", actualTotalBits, bitsRequiredPerCoordinate); - - int encodedX = encodeCoord(chunkX, bitsRequiredPerCoordinate); - int encodedZ = encodeCoord(chunkZ, bitsRequiredPerCoordinate); - DebugLogger.finer("Encoded coordinates: %d, %d", encodedX, encodedZ); - - long combinedValue = ((long) encodedX << bitsRequiredPerCoordinate) | encodedZ; - DebugLogger.finer("Combined value: %d", combinedValue); - - int[] wordIndexes = combinedValueToWordIndexes(combinedValue, wordsRequired); - DebugLogger.finer("Word indexes: %s", Arrays.toString(wordIndexes)); - - return wordList.getWords(wordIndexes); - } - - // Calculates the minimum number of bits required to represent the coordinate - // using the encoding scheme (offset + coord) & mask, such that the coordinate - // fits within the range [-(1 << (bits - 1)), (1 << (bits - 1)) - 1]. - private int findBitsRequiredPerCoordinate(int x, int z) { - int maxVal = Math.max(x, z); - int minVal = Math.min(x, z); - - // Determine the required positive magnitude for the encoding range's positive side. - // We need `(1 << (bits - 1)) >= max(maxVal + 1, -minVal)` - int requiredPositiveMagnitude = Math.max(maxVal + 1, -minVal); - - if (requiredPositiveMagnitude <= 0) { - // Occurs only if maxVal <= -1 and minVal >= 0, which is impossible, - // OR maxVal <= 0 and -minVal <= 0 => maxVal <= 0 and minVal >= 0. - // This means x and z are both 0. - // The range for 1 bit is [-1, 0]. If coords are 0, 1 bit is not enough for offset+coord. - // Example: bits=1. offset=1<<0=1. mask=(1<<1)-1=1. - // encodeCoord(0, 1) = (1+0)&1 = 1. - // decodeCoord(1, 1): val=1. mask=1. offset=1. (1&1)-1 = 0. Correct. - // What if we need to represent -1? encodeCoord(-1, 1) = (1-1)&1 = 0. - // decodeCoord(0, 1): val=0. (0&1)-1 = -1. Correct. - // So 1 bit works for range [-1, 0]. Let's check the condition: - // x=0, z=0 -> maxVal=0, minVal=0. reqPosMag = max(1, 0) = 1. - // x=-1, z=-1 -> maxVal=-1, minVal=-1. reqPosMag = max(0, 1) = 1. - // x=0, z=-1 -> maxVal=0, minVal=-1. reqPosMag = max(1, 1) = 1. - // So requiredPositiveMagnitude is 1 for the range [-1, 0]. - requiredPositiveMagnitude = 1; // Ensure it's at least 1 if coords are 0 or -1. - } - - // Calculate p = bits - 1 - // We need the smallest integer p such that (1 << p) >= requiredPositiveMagnitude. - // If requiredPositiveMagnitude = 1, we need 1 << p >= 1, smallest p is 0. - // If requiredPositiveMagnitude > 1, this is equivalent to finding the number of bits - // needed to represent (requiredPositiveMagnitude - 1) in binary. - int p; - if (requiredPositiveMagnitude == 1) { - p = 0; - } else { - p = 32 - Integer.numberOfLeadingZeros(requiredPositiveMagnitude - 1); - } - - // bits = p + 1 - return p + 1; - } - - private int encodeCoord(int coord, int bitsRequiredPerCoordinate) { - // Bitmask and offset for positive integer conversion - int coordinateMask = (1 << bitsRequiredPerCoordinate) - 1; - int coordinateOffset = 1 << (bitsRequiredPerCoordinate - 1); - - // Encode coordinates with offset into positive range - return (coordinateOffset + coord) & coordinateMask; - } - - private int[] combinedValueToWordIndexes(long combinedValue, int wordsRequired) { - int bitsRequired = wordsRequired * bitsPerWord; - - // Break into word indexes - int[] wordIndexes = new int[wordsRequired]; - int currentIndex = wordsRequired; // Start filling from end of array - - for (int remainingBits = bitsRequired; remainingBits > 0; remainingBits -= bitsPerWord) { - int wordMask = (1 << bitsPerWord) - 1; - wordIndexes[--currentIndex] = (int) (combinedValue & wordMask); - combinedValue >>= bitsPerWord; - } - - return wordIndexes; - } -} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 40473fb..5a84f24 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -8,7 +8,7 @@ api-version: 1.21.1 softdepend: [ProtocolLib] libraries: - - eu.m724:mstats-spigot:0.1.2 + - eu.m724:mstats-spigot:0.1.0 commands: chat: @@ -43,10 +43,6 @@ commands: durabilityalert: description: Durability alert toggle permission: tweaks724.durabilityalert - wordcoords: - description: Word to coords conversion - permission: tweaks724.wordcoords - aliases: [woco, wc, w3w] permissions: tweaks724.chatmanage: @@ -67,8 +63,6 @@ permissions: default: false tweaks724.durabilityalert: default: true - tweaks724.wordcoords: - default: true 7weaks724.ignore.this: description: "Internal, not for use. ${project.spigot.version}" diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index b628eab..be9800a 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -38,10 +38,4 @@ clickToCopy = Click to copy to clipboard clickToExecuteCommand = Click to execute command durabilityEnabled = Enabled durability alert -durabilityDisabled = Disabled durability alert - -# When console executes /wordcoords without arguments -wordCoordsPlayerOnly = Only players can execute this command without arguments. -wordCoordsOutOfRange = Those coordinates are invalid. -wordCoordsInvalidWord = Invalid word: "%s" -wordCoordsNoWords = Please provide the Z coordinate. \ No newline at end of file +durabilityDisabled = Disabled durability alert \ No newline at end of file