From d70d65569f3ddac9444835a378913a847b2e09e7 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 28 Dec 2024 18:52:02 +0100 Subject: [PATCH 01/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 72d9e5c..a965a93 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.9 + 0.1.10-SNAPSHOT 21 @@ -175,6 +175,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.9 + HEAD \ No newline at end of file From e32efe572aa0dccbc3e39433ee64ce6f2abf58a0 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 28 Dec 2024 19:54:27 +0100 Subject: [PATCH 02/89] Better build for other versions --- .forgejo/workflows/build.yml | 8 ++++---- pom.xml | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 6e1abd9..a2ffc8e 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -16,17 +16,17 @@ jobs: - name: Build for 1.21.1 - run: mkdir artifact && mvn clean package && mv target/tweaks-*+1.21.1.jar artifact/ + run: mvn package -Dproject.minecraft.version=1.21.1 -Dproject.nms.version=v1_21_R1 - name: Build for 1.21.3 - run: find src \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/v1_21_R1/v1_21_R2/g" && mvn clean package -Dproject.minecraft.version=1.21.3 && mv target/tweaks-*+1.21.3.jar artifact/ + run: mvn package -Dproject.minecraft.version=1.21.3 -Dproject.nms.version=v1_21_R2 - name: Build for 1.21.4 - run: find src \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/v1_21_R2/v1_21_R3/g" && mvn clean package -Dproject.minecraft.version=1.21.4 && mv target/tweaks-*+1.21.4.jar artifact/ + run: mvn package -Dproject.minecraft.version=1.21.4 -Dproject.nms.version=v1_21_R3 - name: Upload artifacts uses: https://github.com/actions/upload-artifact@v3 with: - path: artifact \ No newline at end of file + path: target \ No newline at end of file diff --git a/pom.xml b/pom.xml index a965a93..384a528 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,8 @@ 21 21 UTF-8 + + v1_21_R1 1.21.1 ${project.minecraft.version}-R0.1-SNAPSHOT @@ -29,6 +31,42 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + custom-nms-version + generate-sources + + run + + + + + + + + + + + cleanup-custom-nms-version + package + + run + + + + + + + + + + + + org.apache.maven.plugins maven-shade-plugin From 8f00220ce393abb5a46d889c96542bf3009703e0 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 28 Dec 2024 19:57:07 +0100 Subject: [PATCH 03/89] [maven-release-plugin] prepare release tweaks-0.1.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 384a528..02650da 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.10-SNAPSHOT + 0.1.10 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.10 \ No newline at end of file From bf5f5515ad637090d13e0a176f70a225bdbc5aa2 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 28 Dec 2024 19:57:09 +0100 Subject: [PATCH 04/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 02650da..4427771 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.10 + 0.1.11-SNAPSHOT 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.10 + HEAD \ No newline at end of file From 3318863cf8f16005c0b599b45b56fa7f090f260f Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 28 Dec 2024 19:57:16 +0100 Subject: [PATCH 05/89] [maven-release-plugin] rollback the release of tweaks-0.1.10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4427771..384a528 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.11-SNAPSHOT + 0.1.10-SNAPSHOT 21 From dde8700248556a4ca09005cd30c12dce62cec122 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 29 Dec 2024 18:40:56 +0100 Subject: [PATCH 06/89] redstone WIP --- README.md | 3 + RETSTONE.md | 32 +++++ retstone.py | 32 +++++ .../java/eu/m724/tweaks/TweaksConfig.java | 11 +- .../java/eu/m724/tweaks/TweaksPlugin.java | 5 + .../tweaks/redstone/RedstoneCommands.java | 52 ++++++++ .../tweaks/redstone/RedstoneListener.java | 54 ++++++++ .../m724/tweaks/redstone/RedstoneManager.java | 101 ++++++++++++++ .../tweaks/redstone/RedstoneRepeaters.java | 126 ++++++++++++++++++ .../redstone/RedstoneStateUpdateRunnable.java | 44 ++++++ src/main/resources/config.yml | 6 + src/main/resources/plugin.yml | 1 + src/main/resources/strings.properties | 4 +- 13 files changed, 468 insertions(+), 3 deletions(-) create mode 100644 RETSTONE.md create mode 100644 retstone.py create mode 100644 src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java create mode 100644 src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java create mode 100644 src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java create mode 100644 src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java create mode 100644 src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java diff --git a/README.md b/README.md index 77f6fe9..4aefca5 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,9 @@ Issue messages that the player needs to read to keep playing, and that make an a `/emergencyalerts` (`tweaks724.emergencyalerts`) +### Remote redstone +Control redstone remotely + ### Utility commands - `/ping` - displays player ping \ diff --git a/RETSTONE.md b/RETSTONE.md new file mode 100644 index 0000000..e406b94 --- /dev/null +++ b/RETSTONE.md @@ -0,0 +1,32 @@ +## Remote redstone + +See [retstone.py](retstone.py) for usage example + +### Glossary +repeaters - the blocks which allow to interact with redstone over internet \ +packet - a bunch of bytes sent over the internet, that do something with a single repeater + +### How it works +A packet is int / 4 bytes / 32 bits + +Packet format: +``` +[ 01 ] [ 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ] [ 29 30 31 32 ] +action bits 2-28 of repeater id payload +``` + +- action: `1` to write, `0` to read +- payload: power level if writing + +If writing, no response \ +If reading, response is the power level, or -1 if no repeater with that id (subject to change) + +Reading powers the block down of course \ +If the block was powered, you should power it down (or read), wait some, and then read again + +### Retstone + +**Network** translates to **reto** in Esperanto \ +So retsomething means networked something (posto - mail, retposto - email, ejo - place (site), retejo - website, etc.) \ +And sometimes we use network instead of internet, same is in that language \ +Hence retstone \ No newline at end of file diff --git a/retstone.py b/retstone.py new file mode 100644 index 0000000..f1bb8dd --- /dev/null +++ b/retstone.py @@ -0,0 +1,32 @@ +# Copyright (C) 2024 Minecon724 +# Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file +# in the project root for the full license text. + +import socket, struct + +ENDPOINT = ("127.0.0.1", 57931) + +def get_power(repeater_id: int) -> int | None: + message = repeater_id & 0x7FFFFFF0 + + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(message.to_bytes(4), ENDPOINT) + + return struct.unpack(">b", sock.recvfrom(1)[0])[0] + +def set_power(repeater_id: int, power: int): + message = repeater_id & 0x7FFFFFF0 + message |= 0x80000000 + message |= power & 0xF + + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(message.to_bytes(4), ENDPOINT) + +repeater_id = 235459920 + +print("Reading from repeater") +power = get_power(repeater_id) +print("Read power:", power) + +print("Powering repeater with power 10") +set_power(repeater_id, 10) \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 53e8972..53a8ba5 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -49,7 +49,10 @@ public record TweaksConfig( boolean authEnabled, boolean authForce, - String authDomain + String authDomain, + + boolean redstoneEnabled, + String redstoneListen ) { public static final int CONFIG_VERSION = 1; private static TweaksConfig config; @@ -113,6 +116,9 @@ public record TweaksConfig( boolean authForce = config.getBoolean("auth.force"); String authHostname = config.getString("auth.domain"); + boolean redstoneEnabled = config.getBoolean("retstone.enabled"); + String redstoneListen = config.getString("retstone.listen"); + TweaksConfig.config = new TweaksConfig( metrics, worldborderExpand, worldborderHide, @@ -125,7 +131,8 @@ public record TweaksConfig( updaterEnabled, hardcoreEnabled, hardcoreChance, sleepEnabled, sleepInstant, - authEnabled, authForce, authHostname + authEnabled, authForce, authHostname, + redstoneEnabled, redstoneListen ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index eff2bf2..dad4bf4 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -20,6 +20,7 @@ import eu.m724.tweaks.ping.PingChecker; import eu.m724.tweaks.ping.PingCommands; import eu.m724.tweaks.pomodoro.PomodoroCommands; import eu.m724.tweaks.pomodoro.PomodoroManager; +import eu.m724.tweaks.redstone.RedstoneManager; import eu.m724.tweaks.sleep.SleepManager; import eu.m724.tweaks.updater.UpdaterCommands; import eu.m724.tweaks.updater.UpdaterManager; @@ -112,6 +113,10 @@ public class TweaksPlugin extends MStatsPlugin { this.getServer().getPluginManager().registerEvents(new FullListener(), this); + if (config.redstoneEnabled()) { + new RedstoneManager(this).init(getCommand("retstone")); + } + if (config.metrics()) mStats(1); diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java new file mode 100644 index 0000000..45522f0 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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.redstone; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class RedstoneCommands implements CommandExecutor { + private final RedstoneRepeaters redstoneRepeaters; + + public RedstoneCommands(RedstoneRepeaters redstoneRepeaters) { + this.redstoneRepeaters = redstoneRepeaters; + } + + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (args.length > 0) { + if (args[0].equals("give")) { + Player player = null; + + if (args.length > 1) { + player = Bukkit.getPlayerExact(args[1]); + if (player == null) { + sender.sendMessage("No player named " + args[1]); + return true; + } + } else { + if (sender instanceof Player) { + player = (Player) sender; + } else { + sender.sendMessage("Specify a player to give to, or be a player"); + } + } + + var itemStack = redstoneRepeaters.give(); + player.getInventory().addItem(itemStack); + } + } else { + sender.sendMessage("Argument needed"); + } + return true; + } +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java new file mode 100644 index 0000000..6a3ef7d --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 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.redstone; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +public class RedstoneListener implements Listener { + private final RedstoneRepeaters redstoneRepeaters; + + public RedstoneListener(RedstoneRepeaters redstoneRepeaters) { + this.redstoneRepeaters = redstoneRepeaters; + } + + @EventHandler + public void onPlace(BlockPlaceEvent event) { + if (!redstoneRepeaters.isRepeater(event.getItemInHand())) return; + + var block = event.getBlockPlaced(); + var id = redstoneRepeaters.onPlace(block); + + System.out.println("repeate place " + id); + } + + @EventHandler + public void onBreak(BlockBreakEvent event) { + var id = redstoneRepeaters.getId(event.getBlock()); + if (id == Integer.MIN_VALUE) return; + + redstoneRepeaters.onBreak(id); + + System.out.println("repeate brek " + id); + } + + @EventHandler + public void a(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getClickedBlock() == null) return; + + var id = redstoneRepeaters.getId(event.getClickedBlock()); + if (id == Integer.MIN_VALUE) return; + + event.getPlayer().sendMessage("Repeater ID: " + id); + } +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java new file mode 100644 index 0000000..b641c3c --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2024 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.redstone; + +import eu.m724.tweaks.TweaksConfig; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.Plugin; + +import java.io.IOException; +import java.net.*; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + +public class RedstoneManager { + private final Plugin plugin; + private final RedstoneRepeaters redstoneRepeaters; + + private DatagramSocket socket; + private RedstoneStateUpdateRunnable runnable; + + public RedstoneManager(Plugin plugin) { + this.plugin = plugin; + this.redstoneRepeaters = new RedstoneRepeaters(plugin); + } + + public void init(PluginCommand command) { + plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneRepeaters), plugin); + command.setExecutor(new RedstoneCommands(redstoneRepeaters)); + + this.runnable = new RedstoneStateUpdateRunnable(redstoneRepeaters); + this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable + + var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":"); + InetSocketAddress bindAddress; + if (listenAddress.length == 1) { + bindAddress = new InetSocketAddress(Integer.parseInt(listenAddress[0])); + } else { + bindAddress = new InetSocketAddress(listenAddress[0], Integer.parseInt(listenAddress[1])); + } + + try { + initSocket(bindAddress); + } catch (SocketException e) { + throw new RuntimeException("Starting socket", e); + } + } + + private void initSocket(SocketAddress bindAddress) throws SocketException { + socket = new DatagramSocket(bindAddress); + + Executors.newSingleThreadExecutor().execute(() -> { + byte[] buf = new byte[4]; + + while (!socket.isClosed()) { + DatagramPacket packet + = new DatagramPacket(buf, buf.length); + try { + socket.receive(packet); + } catch (IOException e) { + System.err.println("Error reading packet: " + e.getMessage()); + continue; + } + + boolean write = (buf[0] >> 7 & 1) == 1; + byte state = (byte) (buf[3] & 0xF); + int repeaterId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0); + + if (write) { + enqueueUpdate(repeaterId, state); + } else { + var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress()); + + enqueueRetrieve(repeaterId, value -> { + System.out.println("retieved state " + value); + newPacket.setData(new byte[] { value }); + + try { + socket.send(newPacket); + } catch (IOException e) { + throw new RuntimeException("Sending response to get repeater value", e); + } + }); + } + } + }); + } + + private void enqueueUpdate(int repeaterId, byte state) { + System.out.println("Update enqueud " + repeaterId + " " + state); + runnable.enqueueUpdate(repeaterId, state); + } + + private void enqueueRetrieve(int repeaterId, Consumer consumer) { + System.out.println("retieve enqueud " + repeaterId); + runnable.enqueueRetrieve(repeaterId, consumer); + } +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java new file mode 100644 index 0000000..5b7bc49 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2024 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.redstone; + +import eu.m724.tweaks.Language; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.plugin.Plugin; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class RedstoneRepeaters { + private final Plugin plugin; + private final NamespacedKey repeaterKey; + + private final Map repeatersById = new HashMap<>(); + private final Map repeatersByLocation = new HashMap<>(); + + public RedstoneRepeaters(Plugin plugin) { + this.plugin = plugin; + this.repeaterKey = new NamespacedKey(plugin, "repeater"); + } + + // + + public boolean isRepeater(ItemStack itemStack) { + var meta = itemStack.getItemMeta(); + if (meta == null) return false; + var value = meta.getPersistentDataContainer().get(repeaterKey, PersistentDataType.BOOLEAN); + return value != null; + } + + public int getId(Block block) { + return repeatersByLocation.getOrDefault(block.getLocation(), Integer.MIN_VALUE); + } + + // + + public ItemStack give() { + var itemStack = new ItemStack(Material.RED_STAINED_GLASS); + var meta = itemStack.getItemMeta(); + + meta.setItemName(Language.getString("retstoneBlockItem")); + meta.getPersistentDataContainer().set(repeaterKey, PersistentDataType.BOOLEAN, true); + meta.setEnchantmentGlintOverride(true); + + itemStack.setItemMeta(meta); + return itemStack; + } + + // TODO save in those + + int onPlace(Block block) { + var repeaterId = ThreadLocalRandom.current().nextInt() & 0x7FFFFFF0; + + repeatersById.put(repeaterId, block.getLocation()); + repeatersByLocation.put(block.getLocation(), repeaterId); + block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId)); + + return repeaterId; + } + + void onBreak(int repeaterId) { + delete(repeaterId); + } + + // + + Block getBlock(int repeaterId) { + var location = repeatersById.get(repeaterId); + if (location == null) return null; + + var storedId = location.getBlock().getMetadata("rid").getFirst().asInt(); + if (storedId != repeaterId) { + System.out.println("retrieved but not exitt"); + delete(repeaterId); + return null; + } + + System.out.println("retrieved exist " + repeaterId); + return location.getBlock(); + } + + void delete(int repeaterId) { + var l = repeatersById.remove(repeaterId); + if (l == null) return; + repeatersByLocation.remove(l); + } + + // + + byte getPower(int repeaterId) { + var block = getBlock(repeaterId); + if (block == null) return -1; + + block.setType(Material.RED_STAINED_GLASS); + + block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); + + return (byte) block.getBlockPower(); + } + + void setPower(int repeaterId, byte power) { + var block = getBlock(repeaterId); + if (block == null) return; + + if (power == 0) + block.setType(Material.RED_STAINED_GLASS); + else + block.setType(Material.REDSTONE_BLOCK); + + block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); + } + +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java new file mode 100644 index 0000000..03d3d38 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 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.redstone; + +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class RedstoneStateUpdateRunnable extends BukkitRunnable { + private Map updateQueue = new HashMap<>(); + private Map> retrieveQueue = new HashMap<>(); + + private final RedstoneRepeaters redstoneRepeaters; + + RedstoneStateUpdateRunnable(RedstoneRepeaters redstoneRepeaters) { + this.redstoneRepeaters = redstoneRepeaters; + } + + void enqueueUpdate(int repeaterId, byte power) { + updateQueue.put(repeaterId, power); + } + + void enqueueRetrieve(int repeaterId, Consumer consumer) { + retrieveQueue.put(repeaterId, consumer); + } + + @Override + public void run() { + var updateQueue = this.updateQueue; + this.updateQueue = new HashMap<>(); + + var retrieveQueue = this.retrieveQueue; + this.retrieveQueue = new HashMap<>(); + + updateQueue.forEach((key, value) -> redstoneRepeaters.setPower(key, value)); + retrieveQueue.forEach((key, value) -> value.accept(redstoneRepeaters.getPower(key))); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a5d2d38..6f58952 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -103,6 +103,12 @@ auth: # The domain of the server. Doesn't do anything other than showing in /tauth new domain: "replace.me" +# Adds blocks which allow to interact with redstone over internet +retstone: + enabled: true + # This takes host:port, listens on UDP + listen: 127.0.0.1:57931 + # Finally, thank you for downloading Tweaks724, I hope you enjoy! # Don't modify unless told to diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c8b67c3..f018798 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -34,6 +34,7 @@ commands: emergencyalert: description: Send emergency alert permission: tweaks724.emergencyalert + retstone: permissions: tweaks724: diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index a7dde07..fd93e94 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -23,4 +23,6 @@ chatAlreadyHere = You're already in this room # Used when a player joins using the wrong key or no key authKickWrongKey = You're connecting to the wrong server address. You must connect to the one you're registered to. # If force is enabled and player is not registered. Changing this reveals you're using this plugin -authKickUnregistered = You are not whitelisted on this server! \ No newline at end of file +authKickUnregistered = You are not whitelisted on this server! + +retstoneBlockItem = Online redstone block \ No newline at end of file From 916f44da47c242c1ccc62f75909972e3e7001b38 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 30 Dec 2024 21:07:47 +0100 Subject: [PATCH 07/89] redstone WIP 2 --- RETSTONE.md | 4 +- retstone.py | 24 ++- .../tweaks/redstone/RedstoneListener.java | 13 ++ .../m724/tweaks/redstone/RedstoneManager.java | 14 +- .../tweaks/redstone/RedstoneRepeaters.java | 150 +++++++++++++----- .../redstone/RedstoneStateUpdateRunnable.java | 2 +- .../java/eu/m724/tweaks/redstone/Store.java | 76 +++++++++ 7 files changed, 231 insertions(+), 52 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/redstone/Store.java diff --git a/RETSTONE.md b/RETSTONE.md index e406b94..8f299d8 100644 --- a/RETSTONE.md +++ b/RETSTONE.md @@ -19,10 +19,10 @@ action bits 2-28 of repeater id - payload: power level if writing If writing, no response \ -If reading, response is the power level, or -1 if no repeater with that id (subject to change) +If reading, response is the power level, or 0 if not powered or no repeater with that ID Reading powers the block down of course \ -If the block was powered, you should power it down (or read), wait some, and then read again +BUT you should power it down (or read), wait some, and then read again ### Retstone diff --git a/retstone.py b/retstone.py index f1bb8dd..8bfeb7d 100644 --- a/retstone.py +++ b/retstone.py @@ -22,11 +22,23 @@ def set_power(repeater_id: int, power: int): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(message.to_bytes(4), ENDPOINT) -repeater_id = 235459920 -print("Reading from repeater") -power = get_power(repeater_id) -print("Read power:", power) +if __name__ == "__main__": + from argparse import ArgumentParser -print("Powering repeater with power 10") -set_power(repeater_id, 10) \ No newline at end of file + parser = ArgumentParser() + parser.add_argument("repeater_id", help="The repeater ID", type=int) + parser.add_argument("-p", "--power", help="Power the repeater with specified power. Leave to read.", type=int) + parser.add_argument("-c", "--copy", help="Copy input of one repeater to another. If combined with power, power is added.", type=int) + args = parser.parse_args() + + if args.copy is None: + if args.power is None: + power = get_power(args.repeater_id) + print(power) + else: + set_power(args.repeater_id, args.power) + else: + while True: + power = get_power(args.repeater_id) + set_power(args.copy, power) \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java index 6a3ef7d..c0f270c 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java @@ -51,4 +51,17 @@ public class RedstoneListener implements Listener { event.getPlayer().sendMessage("Repeater ID: " + id); } + + @EventHandler + public void b(BlockRedstoneEvent event) { + var block = event.getBlock(); + System.out.println(block); + + var id = redstoneRepeaters.getId(block); + if (id == Integer.MIN_VALUE) return; + + System.out.println("yes it isi"); + + event.setNewCurrent(redstoneRepeaters.getOutboundPower(id)); + } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java index b641c3c..431bfc3 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java @@ -28,6 +28,8 @@ public class RedstoneManager { } public void init(PluginCommand command) { + Store.init(plugin); + plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneRepeaters), plugin); command.setExecutor(new RedstoneCommands(redstoneRepeaters)); @@ -66,17 +68,17 @@ public class RedstoneManager { } boolean write = (buf[0] >> 7 & 1) == 1; - byte state = (byte) (buf[3] & 0xF); + byte data = (byte) (buf[3] & 0xF); int repeaterId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0); if (write) { - enqueueUpdate(repeaterId, state); + enqueueUpdate(repeaterId, data); } else { var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress()); enqueueRetrieve(repeaterId, value -> { System.out.println("retieved state " + value); - newPacket.setData(new byte[] { value }); + newPacket.setData(new byte[] { (byte) Math.max(value, 0) }); try { socket.send(newPacket); @@ -89,9 +91,9 @@ public class RedstoneManager { }); } - private void enqueueUpdate(int repeaterId, byte state) { - System.out.println("Update enqueud " + repeaterId + " " + state); - runnable.enqueueUpdate(repeaterId, state); + private void enqueueUpdate(int repeaterId, byte power) { + System.out.println("Update enqueud " + repeaterId + " " + power); + runnable.enqueueUpdate(repeaterId, power); } private void enqueueRetrieve(int repeaterId, Consumer consumer) { diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java index 5b7bc49..77b1a77 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java @@ -6,49 +6,40 @@ package eu.m724.tweaks.redstone; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import eu.m724.tweaks.Language; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Particle; import org.bukkit.block.Block; +import org.bukkit.block.data.AnaloguePowerable; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.persistence.PersistentDataType; import org.bukkit.plugin.Plugin; -import java.util.*; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ThreadLocalRandom; public class RedstoneRepeaters { private final Plugin plugin; private final NamespacedKey repeaterKey; - private final Map repeatersById = new HashMap<>(); - private final Map repeatersByLocation = new HashMap<>(); + private final BiMap repeatersById = HashBiMap.create(); + private final Map repeatersByPower = new HashMap<>(); public RedstoneRepeaters(Plugin plugin) { this.plugin = plugin; this.repeaterKey = new NamespacedKey(plugin, "repeater"); } - // - - public boolean isRepeater(ItemStack itemStack) { - var meta = itemStack.getItemMeta(); - if (meta == null) return false; - var value = meta.getPersistentDataContainer().get(repeaterKey, PersistentDataType.BOOLEAN); - return value != null; - } - - public int getId(Block block) { - return repeatersByLocation.getOrDefault(block.getLocation(), Integer.MIN_VALUE); - } - - // + /* Item functions */ public ItemStack give() { - var itemStack = new ItemStack(Material.RED_STAINED_GLASS); + var itemStack = new ItemStack(Material.DAYLIGHT_DETECTOR); var meta = itemStack.getItemMeta(); meta.setItemName(Language.getString("retstoneBlockItem")); @@ -59,15 +50,23 @@ public class RedstoneRepeaters { return itemStack; } - // TODO save in those + public boolean isRepeater(ItemStack itemStack) { + var meta = itemStack.getItemMeta(); + if (meta == null) return false; + var value = meta.getPersistentDataContainer().get(repeaterKey, PersistentDataType.BOOLEAN); + return value != null; + } + + /* Event */ int onPlace(Block block) { var repeaterId = ThreadLocalRandom.current().nextInt() & 0x7FFFFFF0; repeatersById.put(repeaterId, block.getLocation()); - repeatersByLocation.put(block.getLocation(), repeaterId); block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId)); + Store.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0); + return repeaterId; } @@ -75,12 +74,83 @@ public class RedstoneRepeaters { delete(repeaterId); } - // + void delete(int repeaterId) { + var location = repeatersById.remove(repeaterId); + if (location == null) return; + repeatersByPower.remove(repeaterId); + + Store.getInstance().deleteSavedRepeaterData(location); + } + + /* Get functions */ + + private boolean isValid(int repeaterId) { + // check if there's a repeater with such ID stored + // if not, we're not loading because it's loaded as the block is + var loc = repeatersById.get(repeaterId); + if (loc == null) { + System.err.println("Delete because no loc"); + delete(repeaterId); + return false; + } + + // check if chunk the block is in is loaded + // you may think it could be simplified, but it can't without loading the chunk (to check if it's loaded) + var isLoaded = loc.getWorld().isChunkLoaded(loc.getBlockX() / 16, loc.getBlockZ() / 16); + if (!isLoaded) return false; + + // check if the block is correct type + if (loc.getBlock().getType() != Material.DAYLIGHT_DETECTOR) { + delete(repeaterId); + return false; + } + + // check if the block has the same ID bound + var meta = loc.getBlock().getMetadata("rid"); + if (meta.isEmpty() || meta.getFirst().asInt() != repeaterId) { + System.err.println("Delete because no meta"); + delete(repeaterId); + return false; + } + + return true; + } + + public int getId(Block block) { + if (block.hasMetadata("rid")) { + var id = block.getMetadata("rid").getFirst().asInt(); + return id; + } + + var id = repeatersById.inverse().get(block.getLocation()); + + if (id == null) { + // not in memory, check if repeater + var d = Store.getInstance().getSavedRepeaterData(block.getLocation()); + + if (d == null) { + block.setMetadata("rid", new FixedMetadataValue(plugin, Integer.MIN_VALUE)); + return Integer.MIN_VALUE; + } + + id = d.getKey(); + block.setMetadata("rid", new FixedMetadataValue(plugin, id)); + + repeatersById.put(id, block.getLocation()); + repeatersByPower.put(id, d.getValue()); + } + + if (!isValid(id)) return Integer.MIN_VALUE; + + return id; + } Block getBlock(int repeaterId) { var location = repeatersById.get(repeaterId); if (location == null) return null; + if (!isValid(repeaterId)) return null; + var storedId = location.getBlock().getMetadata("rid").getFirst().asInt(); if (storedId != repeaterId) { System.out.println("retrieved but not exitt"); @@ -92,35 +162,41 @@ public class RedstoneRepeaters { return location.getBlock(); } - void delete(int repeaterId) { - var l = repeatersById.remove(repeaterId); - if (l == null) return; - repeatersByLocation.remove(l); - } + /* Control functions */ - // - - byte getPower(int repeaterId) { + byte getInboundPower(int repeaterId) { var block = getBlock(repeaterId); if (block == null) return -1; - block.setType(Material.RED_STAINED_GLASS); - block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); + System.out.println("Okay I got in power" + block.getBlockPower()); return (byte) block.getBlockPower(); } + byte getOutboundPower(int repeaterId) { + var block = getBlock(repeaterId); + if (block == null) return -1; + + System.out.println("Okay I got out power" + repeatersByPower.get(repeaterId)); + return repeatersByPower.getOrDefault(repeaterId, (byte) 0); + } + void setPower(int repeaterId, byte power) { + System.out.println(power); + if (power < 0 || power > 15) + throw new IllegalArgumentException("Power should be 0-15, but is " + power); + var block = getBlock(repeaterId); if (block == null) return; - if (power == 0) - block.setType(Material.RED_STAINED_GLASS); - else - block.setType(Material.REDSTONE_BLOCK); + var data = (AnaloguePowerable) block.getBlockData(); + + repeatersByPower.put(repeaterId, power); + data.setPower(power); block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); - } -} + System.out.println("Okay I set power"); + } +} \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java index 03d3d38..4368f68 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java @@ -39,6 +39,6 @@ public class RedstoneStateUpdateRunnable extends BukkitRunnable { this.retrieveQueue = new HashMap<>(); updateQueue.forEach((key, value) -> redstoneRepeaters.setPower(key, value)); - retrieveQueue.forEach((key, value) -> value.accept(redstoneRepeaters.getPower(key))); + retrieveQueue.forEach((key, value) -> value.accept(redstoneRepeaters.getInboundPower(key))); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/Store.java b/src/main/java/eu/m724/tweaks/redstone/Store.java new file mode 100644 index 0000000..d9d8ff8 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/Store.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 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.redstone; + +import com.google.common.primitives.Ints; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Location; +import org.bukkit.plugin.Plugin; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class Store { + private static Store INSTANCE; + + private final Plugin plugin; + private final File directory; + + private Store(Plugin plugin) { + this.plugin = plugin; + this.directory = new File(plugin.getDataFolder(), "storage/redstone"); + directory.mkdirs(); + } + + static void init(Plugin plugin) { + INSTANCE = new Store(plugin); + } + + static Store getInstance() { + return INSTANCE; + } + + Pair getSavedRepeaterData(Location location) { + var file = getFile(location); + if (!file.exists()) return null; + + byte[] bytes; + + try { + // TODO read just 4 bytes + bytes = Files.readAllBytes(file.toPath()); + } catch (IOException e) { + throw new RuntimeException("Loading saved repeater data", e); + } + + var repeaterId = Ints.fromByteArray(bytes) & ~0xF; + var powerLevel = (byte) (bytes[3] & 0xF); + + return Pair.of(repeaterId, powerLevel); + } + + void saveRepeaterData(Location location, int repeaterId, byte powerLevel) { + var file = getFile(location); + System.out.println(file); + byte[] bytes = Ints.toByteArray((repeaterId & ~0xF) | (powerLevel & 0xF)); + + try { + Files.write(file.toPath(), bytes); + } catch (IOException e) { + throw new RuntimeException("Saving repeater data", e); + } + } + + void deleteSavedRepeaterData(Location location) { + getFile(location).delete(); + } + + private File getFile(Location location) { + return new File(directory, location.getWorld().getName() + " " + location.getBlockX() + " " + location.getBlockY() + " " + location.getBlockZ()); + } +} From d92222158976b1e8834f5f88aff6fe050135ceeb Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 13:34:17 +0100 Subject: [PATCH 08/89] Refactoring and clean ups --- src/main/java/eu/m724/tweaks/DebugLogger.java | 51 +++++++++ src/main/java/eu/m724/tweaks/Language.java | 6 +- .../java/eu/m724/tweaks/TweaksConfig.java | 10 +- .../java/eu/m724/tweaks/TweaksPlugin.java | 102 ++++++++++-------- .../java/eu/m724/tweaks/chat/ChatManager.java | 8 +- .../java/eu/m724/tweaks/door/DoorManager.java | 24 ----- .../java/eu/m724/tweaks/motd/MotdManager.java | 10 +- .../java/eu/m724/tweaks/ping/PingChecker.java | 7 +- .../m724/tweaks/pomodoro/PomodoroManager.java | 5 +- .../tweaks/pomodoro/PomodoroRunnable.java | 3 +- .../eu/m724/tweaks/pomodoro/Pomodoros.java | 4 +- .../tweaks/redstone/RedstoneListener.java | 19 ++-- .../m724/tweaks/redstone/RedstoneManager.java | 9 +- .../eu/m724/tweaks/updater/PluginScanner.java | 1 - .../eu/m724/tweaks/updater/UpdateChecker.java | 2 +- .../m724/tweaks/updater/UpdaterCommands.java | 6 +- .../m724/tweaks/updater/UpdaterManager.java | 16 ++- ...Listener.java => WorldBorderExpander.java} | 12 ++- .../worldborder/WorldBorderManager.java | 29 ----- src/main/resources/strings.properties | 8 +- 20 files changed, 199 insertions(+), 133 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/DebugLogger.java delete mode 100644 src/main/java/eu/m724/tweaks/door/DoorManager.java rename src/main/java/eu/m724/tweaks/worldborder/{WorldBorderExpanderListener.java => WorldBorderExpander.java} (72%) delete mode 100644 src/main/java/eu/m724/tweaks/worldborder/WorldBorderManager.java diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java new file mode 100644 index 0000000..45b7ba5 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/DebugLogger.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 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; + +import org.fusesource.jansi.Ansi; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class DebugLogger { + static Logger logger; + + public static void info(String message) { + log(Level.INFO, message); + } + + public static void warning(String message) { + log(Level.WARNING, message); + } + + public static void severe(String message) { + log(Level.SEVERE, message); + } + + public static void fine(String message) { + log(Level.FINE, message); + } + + private static void log(Level level, String message) { + if (logger.getLevel().intValue() > level.intValue()) return; + + var caller = Thread.currentThread().getStackTrace()[3].getClassName(); + + if (caller.startsWith("eu.m724.tweaks.")) + caller = caller.substring(15); + + message = "[" + caller + "] " + message; + + if (level.intValue() < Level.INFO.intValue()) { // levels below info are never logged even if set for some reason + level = Level.INFO; + // colors text gray (cyan is close to gray) + message = Ansi.ansi().fg(Ansi.Color.CYAN).a(message).reset().toString(); + } + + logger.log(level, message); + } +} diff --git a/src/main/java/eu/m724/tweaks/Language.java b/src/main/java/eu/m724/tweaks/Language.java index 5cefae6..55a2d33 100644 --- a/src/main/java/eu/m724/tweaks/Language.java +++ b/src/main/java/eu/m724/tweaks/Language.java @@ -28,11 +28,15 @@ public class Language { return INSTANCE.resourceBundle.getString(key); } + public static String getString(String key, Object... format) { + return INSTANCE.resourceBundle.getString(key).formatted(format); + } + public static BaseComponent getComponent(String key, ChatColor color) { return new ComponentBuilder(getString(key)).color(color).build(); } public static BaseComponent getComponent(String key, ChatColor color, Object... format) { - return new ComponentBuilder(getString(key).formatted(format)).color(color).build(); + return new ComponentBuilder(getString(key, format)).color(color).build(); } } diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 53a8ba5..2c71c1f 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -11,6 +11,8 @@ import org.bukkit.plugin.Plugin; public record TweaksConfig( boolean metrics, + boolean debug, + String locale, boolean worldborderExpand, boolean worldborderHide, @@ -20,7 +22,6 @@ public record TweaksConfig( boolean brandShowPing, boolean brandShowMspt, - boolean doorEnabled, boolean doorDoubleOpen, boolean doorKnocking, @@ -76,6 +77,8 @@ public record TweaksConfig( } boolean metrics = config.getBoolean("metrics"); + boolean debug = config.getBoolean("debug", false); + String locale = config.getString("locale", "US"); boolean worldborderExpand = config.getBoolean("worldborder.expand"); boolean worldborderHide = config.getBoolean("worldborder.hide"); @@ -87,7 +90,6 @@ public record TweaksConfig( boolean doorDoubleOpen = config.getBoolean("doors.doubleOpen"); boolean doorKnocking = config.getBoolean("doors.knocking"); - boolean doorEnabled = doorDoubleOpen || doorKnocking; String motdSet = config.getString("motd.set"); boolean motdEnabled = !(motdSet.equals("false") || motdSet.isBlank()); @@ -120,10 +122,10 @@ public record TweaksConfig( String redstoneListen = config.getString("retstone.listen"); TweaksConfig.config = new TweaksConfig( - metrics, + debug, metrics, locale, worldborderExpand, worldborderHide, brandEnabled, brandText, brandShowPing, brandShowMspt, - doorEnabled, doorDoubleOpen, doorKnocking, + doorDoubleOpen, doorKnocking, motdEnabled, motdSet, chatEnabled, chatLocalEvents, chatDefaultName, chatRadius, compassEnabled, compassWidth, compassPrecision, diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index dad4bf4..f1e705e 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -9,26 +9,23 @@ package eu.m724.tweaks; import eu.m724.mstats.MStatsPlugin; import eu.m724.tweaks.alert.AlertManager; import eu.m724.tweaks.auth.AuthManager; -import eu.m724.tweaks.chat.ChatCommands; import eu.m724.tweaks.chat.ChatManager; -import eu.m724.tweaks.door.DoorManager; +import eu.m724.tweaks.door.DoorKnockListener; +import eu.m724.tweaks.door.DoorOpenListener; import eu.m724.tweaks.full.FullListener; import eu.m724.tweaks.hardcore.HardcoreManager; import eu.m724.tweaks.motd.MotdManager; import eu.m724.tweaks.ping.F3NameListener; import eu.m724.tweaks.ping.PingChecker; -import eu.m724.tweaks.ping.PingCommands; -import eu.m724.tweaks.pomodoro.PomodoroCommands; import eu.m724.tweaks.pomodoro.PomodoroManager; import eu.m724.tweaks.redstone.RedstoneManager; import eu.m724.tweaks.sleep.SleepManager; -import eu.m724.tweaks.updater.UpdaterCommands; import eu.m724.tweaks.updater.UpdaterManager; -import eu.m724.tweaks.worldborder.WorldBorderManager; +import eu.m724.tweaks.worldborder.WorldBorderExpander; +import eu.m724.tweaks.worldborder.WorldBorderHider; -import java.io.IOException; import java.util.Locale; -import java.util.Objects; +import java.util.logging.Level; public class TweaksPlugin extends MStatsPlugin { @Override @@ -43,84 +40,99 @@ public class TweaksPlugin extends MStatsPlugin { } TweaksConfig config = TweaksConfig.load(this); - new Language(Locale.US); // TODO - // whether enabled is handled inside - new WorldBorderManager().init(this); + getLogger().setLevel(config.debug() ? Level.FINEST : Level.INFO); + DebugLogger.logger = getLogger(); + DebugLogger.fine("Debug enabled. There may be performance issues."); - if (config.chatEnabled()) { - ChatManager chatManager = new ChatManager(this); - chatManager.init(); + DebugLogger.fine("Enabling Language"); + new Language(Locale.of(config.locale())); // TODO + DebugLogger.fine(Language.getString("languageNotice", Language.getString("language"), Language.getString("languageEnglish"))); - ChatCommands chatCommands = new ChatCommands(chatManager); - Objects.requireNonNull(getCommand("chat")).setExecutor(chatCommands); - Objects.requireNonNull(getCommand("chatmanage")).setExecutor(chatCommands); + /* start modules */ + + if (config.worldborderHide()) { + DebugLogger.fine("Enabling Worldborder hide"); + new WorldBorderHider().init(this); } - if (config.doorEnabled()) { - new DoorManager().init(this); + if (config.worldborderExpand()) { + DebugLogger.fine("Enabling Worldborder expand"); + new WorldBorderExpander().init(this); + } + + if (config.chatEnabled()) { + DebugLogger.fine("Enabling Chat"); + new ChatManager(this).init(getCommand("chat"), getCommand("chatmanage")); + } + + if (config.doorKnocking()) { + DebugLogger.fine("Enabling Door knock"); + getServer().getPluginManager().registerEvents(new DoorKnockListener(), this); + } + + if (config.doorDoubleOpen()) { + DebugLogger.fine("Enabling Door double open"); + getServer().getPluginManager().registerEvents(new DoorOpenListener(), this); } if (config.brandEnabled()) { + DebugLogger.fine("Enabling Brand"); new F3NameListener(this).init(); } - new PingChecker(this).init(); - Objects.requireNonNull(getCommand("ping")).setExecutor(new PingCommands()); - - /*if (getServer().getPluginManager().getPlugin("voicechat") != null) { - new MusicPlayer(this).init(); - } else { - getLogger().warning("To use voice extensions, install \"Simple Voice Chat\""); - }*/ + DebugLogger.fine("Enabling Ping"); + new PingChecker(this).init(getCommand("ping")); if (config.motdEnabled()) { - try { - new MotdManager(this).init(); - } catch (IOException e) { - getLogger().severe("Failed to initialize MOTD extension"); - throw new RuntimeException(e); - } + DebugLogger.fine("Enabling MOTD"); + new MotdManager(this).init(); } if (config.pomodoroEnabled()) { - new PomodoroManager(this).init(); - getCommand("pomodoro").setExecutor(new PomodoroCommands()); + DebugLogger.fine("Enabling Pomodoro"); + new PomodoroManager(this).init(getCommand("pomodoro")); } if (config.updaterEnabled()) { - try { - new UpdaterManager(this).init(); - getCommand("updates").setExecutor(new UpdaterCommands()); - } catch (IOException e) { - throw new RuntimeException(e); - } + DebugLogger.fine("Enabling Updater"); + new UpdaterManager(this).init(getCommand("updates")); } if (config.hardcoreEnabled()) { + DebugLogger.fine("Enabling Hardcore"); new HardcoreManager().init(this); } if (config.sleepEnabled()) { + DebugLogger.fine("Enabling Sleep"); new SleepManager().init(this); } if (config.authEnabled()) { + DebugLogger.fine("Enabling Auth"); new AuthManager(this).init(getCommand("tauth")); } + DebugLogger.fine("Enabling Alert"); new AlertManager(this).init(getCommand("emergencyalert")); - this.getServer().getPluginManager().registerEvents(new FullListener(), this); + DebugLogger.fine("Enabling Full"); + getServer().getPluginManager().registerEvents(new FullListener(), this); if (config.redstoneEnabled()) { + DebugLogger.fine("Enabling Redstone"); new RedstoneManager(this).init(getCommand("retstone")); } - if (config.metrics()) - mStats(1); + /* end modules */ - getLogger().info("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); + if (config.metrics()) { + DebugLogger.fine("Enabling Metrics"); + mStats(1); + } + + DebugLogger.fine("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); } public boolean hasResource(String resource) { diff --git a/src/main/java/eu/m724/tweaks/chat/ChatManager.java b/src/main/java/eu/m724/tweaks/chat/ChatManager.java index ec4461f..89b1ff1 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatManager.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatManager.java @@ -11,6 +11,7 @@ import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; +import org.bukkit.command.PluginCommand; import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; import org.bukkit.plugin.Plugin; @@ -18,6 +19,7 @@ import org.bukkit.plugin.Plugin; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public class ChatManager { private final Plugin plugin; @@ -33,13 +35,17 @@ public class ChatManager { this.defaultRoom = TweaksConfig.getConfig().chatDefaultName(); } - public void init() { + public void init(PluginCommand chatCommand, PluginCommand chatManageCommand) { if (plugin.getServer().isEnforcingSecureProfiles()) { throw new RuntimeException("Please disable enforce-secure-profile in server.properties to use chatrooms"); } getById(defaultRoom); plugin.getServer().getPluginManager().registerEvents(new ChatListener(this), plugin); + + var chatCommands = new ChatCommands(this); + chatCommand.setExecutor(chatCommands); + chatManageCommand.setExecutor(chatCommands); } /** diff --git a/src/main/java/eu/m724/tweaks/door/DoorManager.java b/src/main/java/eu/m724/tweaks/door/DoorManager.java deleted file mode 100644 index 52553b5..0000000 --- a/src/main/java/eu/m724/tweaks/door/DoorManager.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2024 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.door; - -import eu.m724.tweaks.TweaksConfig; -import org.bukkit.plugin.Plugin; - -public class DoorManager { - - public void init(Plugin plugin) { - if (TweaksConfig.getConfig().doorKnocking()) { - plugin.getServer().getPluginManager().registerEvents(new DoorKnockListener(), plugin); - } - - if (TweaksConfig.getConfig().doorDoubleOpen()) { - plugin.getServer().getPluginManager().registerEvents(new DoorOpenListener(), plugin); - } - } - -} diff --git a/src/main/java/eu/m724/tweaks/motd/MotdManager.java b/src/main/java/eu/m724/tweaks/motd/MotdManager.java index 4ef367b..1748ae8 100644 --- a/src/main/java/eu/m724/tweaks/motd/MotdManager.java +++ b/src/main/java/eu/m724/tweaks/motd/MotdManager.java @@ -37,7 +37,7 @@ public class MotdManager { this.plugin = plugin; } - public void init() throws IOException { + public void init() { // TODO adding more MOTD features would require checking whether to enable set String motdSetName = TweaksConfig.getConfig().motdSet(); @@ -55,7 +55,13 @@ public class MotdManager { throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(motdSetName)); } - String fileContent = Files.readString(motdSetsFile.toPath()); + String fileContent = null; + try { + fileContent = Files.readString(motdSetsFile.toPath()); + } catch (IOException e) { + throw new RuntimeException("Reading motd set", e); + } + // MOTDs are split with an empty line motds = Arrays.stream(fileContent.split("\n\n")) .map(s -> { diff --git a/src/main/java/eu/m724/tweaks/ping/PingChecker.java b/src/main/java/eu/m724/tweaks/ping/PingChecker.java index d5d982f..41e95ab 100644 --- a/src/main/java/eu/m724/tweaks/ping/PingChecker.java +++ b/src/main/java/eu/m724/tweaks/ping/PingChecker.java @@ -6,8 +6,11 @@ package eu.m724.tweaks.ping; +import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; +import java.util.Objects; + public class PingChecker { private final Plugin plugin; @@ -15,8 +18,10 @@ public class PingChecker { this.plugin = plugin; } - public void init() { + public void init(PluginCommand pingCommand) { new KeepAlivePingChecker(plugin).start(); new MsptChecker().init(plugin); // TODO should this be here + + pingCommand.setExecutor(new PingCommands()); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java index bc1dcaf..0483042 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.pomodoro; +import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; public class PomodoroManager { @@ -15,8 +16,10 @@ public class PomodoroManager { this.plugin = plugin; } - public void init() { + public void init(PluginCommand pomodoroCommand) { plugin.getServer().getPluginManager().registerEvents(new PomodoroListener(), plugin); new PomodoroRunnable(plugin).runTaskTimerAsynchronously(plugin, 0, 20L); + + pomodoroCommand.setExecutor(new PomodoroCommands()); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java index 08a170c..c88b920 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java @@ -37,7 +37,8 @@ public class PomodoroRunnable extends BukkitRunnable { player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f); if (remaining < -60 && force) { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { - player.kickPlayer(Language.getString("pomodoroEndKick")); + pomodoro.next(); + player.kickPlayer(Language.getString("pomodoroEndKick") + "\n" + Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now))); }); } } diff --git a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java index 799d08c..10044f9 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java @@ -30,7 +30,7 @@ public class Pomodoros { return timers.remove(player.getUniqueId()) != null; } - static BaseComponent[] formatTimer(PlayerPomodoro pomodoro, long remaining) { + static BaseComponent formatTimer(PlayerPomodoro pomodoro, long remaining) { ComponentBuilder builder = new ComponentBuilder(); if (pomodoro.isBreak()) { @@ -66,6 +66,6 @@ public class Pomodoros { builder.append(" o").color(color); } - return builder.create(); + return builder.build(); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java index c0f270c..1883a49 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.redstone; +import eu.m724.tweaks.DebugLogger; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; @@ -22,46 +23,46 @@ public class RedstoneListener implements Listener { } @EventHandler - public void onPlace(BlockPlaceEvent event) { + public void onBlockPlace(BlockPlaceEvent event) { if (!redstoneRepeaters.isRepeater(event.getItemInHand())) return; var block = event.getBlockPlaced(); var id = redstoneRepeaters.onPlace(block); - System.out.println("repeate place " + id); + DebugLogger.fine("Repeater placed: " + id); } @EventHandler - public void onBreak(BlockBreakEvent event) { + public void onBlockBreak(BlockBreakEvent event) { var id = redstoneRepeaters.getId(event.getBlock()); if (id == Integer.MIN_VALUE) return; redstoneRepeaters.onBreak(id); - System.out.println("repeate brek " + id); + DebugLogger.fine("Repeater broken: " + id); } @EventHandler - public void a(PlayerInteractEvent event) { + public void onPlayerInteract(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (event.getClickedBlock() == null) return; var id = redstoneRepeaters.getId(event.getClickedBlock()); if (id == Integer.MIN_VALUE) return; + // TODO find a less lame way of showing ID event.getPlayer().sendMessage("Repeater ID: " + id); } @EventHandler - public void b(BlockRedstoneEvent event) { + public void onBlockRedstone(BlockRedstoneEvent event) { var block = event.getBlock(); - System.out.println(block); var id = redstoneRepeaters.getId(block); if (id == Integer.MIN_VALUE) return; - System.out.println("yes it isi"); - event.setNewCurrent(redstoneRepeaters.getOutboundPower(id)); + + DebugLogger.fine("Repeater redstone event: " + id); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java index 431bfc3..d4491d5 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.redstone; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; @@ -63,7 +64,7 @@ public class RedstoneManager { try { socket.receive(packet); } catch (IOException e) { - System.err.println("Error reading packet: " + e.getMessage()); + DebugLogger.severe("Error reading packet: " + e.getMessage()); continue; } @@ -77,7 +78,7 @@ public class RedstoneManager { var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress()); enqueueRetrieve(repeaterId, value -> { - System.out.println("retieved state " + value); + DebugLogger.fine("Retrieved for " + repeaterId + " power " + value); newPacket.setData(new byte[] { (byte) Math.max(value, 0) }); try { @@ -92,12 +93,12 @@ public class RedstoneManager { } private void enqueueUpdate(int repeaterId, byte power) { - System.out.println("Update enqueud " + repeaterId + " " + power); + DebugLogger.fine("Update enqueued " + repeaterId + " " + power); runnable.enqueueUpdate(repeaterId, power); } private void enqueueRetrieve(int repeaterId, Consumer consumer) { - System.out.println("retieve enqueud " + repeaterId); + DebugLogger.fine("Retrieve enqueued " + repeaterId); runnable.enqueueRetrieve(repeaterId, consumer); } } diff --git a/src/main/java/eu/m724/tweaks/updater/PluginScanner.java b/src/main/java/eu/m724/tweaks/updater/PluginScanner.java index ac4a921..a437b1c 100644 --- a/src/main/java/eu/m724/tweaks/updater/PluginScanner.java +++ b/src/main/java/eu/m724/tweaks/updater/PluginScanner.java @@ -36,7 +36,6 @@ public class PluginScanner { Set spigotResources = new HashSet<>(); for (Plugin plugin : plugins) { - // System.out.println("Found " + plugin.getName()); String pluginName = plugin.getName(); if (!configuration.isSet(pluginName)) { diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java index 5216e2b..61f0fb8 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java @@ -70,7 +70,7 @@ public class UpdateChecker extends BukkitRunnable { private void alert() { int n = availableUpdates.size(); if (n == 0) return; - logger.info(Language.getString("updateAvailableNotice").formatted(n)); + logger.info(Language.getString("updateAvailableNotice", n)); availableUpdates.stream() .map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label())) diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java index 731255c..46b7c9e 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java @@ -35,7 +35,7 @@ public class UpdaterCommands implements CommandExecutor { if (n > 0) { sender.spigot().sendMessage( - new ComponentBuilder(Language.getString("updateAvailableNotice").formatted(n)).color(ChatColor.GRAY).build() + Language.getComponent("updateAvailableNotice", ChatColor.GRAY, n) ); int i = 0; @@ -45,7 +45,7 @@ public class UpdaterCommands implements CommandExecutor { ); } } else { - sender.sendMessage(Language.getString("updatesNoUpdates").formatted(lastChecked)); + sender.spigot().sendMessage(Language.getComponent("updatesNoUpdates", ChatColor.GREEN, lastChecked)); } return true; @@ -71,7 +71,7 @@ public class UpdaterCommands implements CommandExecutor { .event( new HoverEvent( HoverEvent.Action.SHOW_TEXT, - new Text(Language.getString("updatesClickToOpen").formatted(v.latest().description().title())) + new Text(Language.getString("updatesClickToOpen", v.latest().description().title())) ) ) .build(); diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java index e335ce2..6fa06b0 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java @@ -6,9 +6,11 @@ package eu.m724.tweaks.updater; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.updater.cache.ResourceVersion; import eu.m724.tweaks.updater.cache.SpigotResource; import eu.m724.tweaks.updater.cache.VersionedResource; +import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; import java.io.File; @@ -29,9 +31,14 @@ public class UpdaterManager { cacheFile = new File(plugin.getDataFolder(), "cache/updater"); } - public void init() throws IOException { + public void init(PluginCommand updatesCommand){ // scan installed plugins - Set resources = new PluginScanner(plugin).load(); + Set resources = null; + try { + resources = new PluginScanner(plugin).load(); + } catch (IOException e) { + throw new RuntimeException("Loading plugins", e); + } cacheFile.getParentFile().mkdirs(); // TODO move this somewhere else @@ -41,6 +48,9 @@ public class UpdaterManager { installedVersions = VersionCheckCache.loadAll(inputStream); } catch (FileNotFoundException e) { installedVersions = new HashSet<>(); + } catch (IOException e) { + DebugLogger.warning("Error loading installed version cache, starting fresh. " + e.getMessage()); + installedVersions = new HashSet<>(); } final Set ivf = installedVersions; @@ -52,5 +62,7 @@ public class UpdaterManager { new UpdateChecker(plugin, versionedResources) .runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20); + + updatesCommand.setExecutor(new UpdaterCommands()); } } diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpanderListener.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java similarity index 72% rename from src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpanderListener.java rename to src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java index e94051c..14eae1b 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpanderListener.java +++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java @@ -11,8 +11,18 @@ import org.bukkit.craftbukkit.v1_21_R1.CraftWorld; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.plugin.Plugin; + +public class WorldBorderExpander implements Listener { + public void init(Plugin plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + + // because the plugin loads "post world" + plugin.getServer().getWorlds().forEach(w -> { + onWorldLoad(new WorldLoadEvent(w)); + }); + } -public class WorldBorderExpanderListener implements Listener { @EventHandler public void onWorldLoad(WorldLoadEvent event) { ServerLevel level = ((CraftWorld) event.getWorld()).getHandle(); diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderManager.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderManager.java deleted file mode 100644 index 2354a83..0000000 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderManager.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2024 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.worldborder; - -import eu.m724.tweaks.TweaksConfig; -import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.plugin.Plugin; - -public class WorldBorderManager { - public void init(Plugin plugin) { - if (TweaksConfig.getConfig().worldborderExpand()) { - WorldBorderExpanderListener wbrl = new WorldBorderExpanderListener(); - plugin.getServer().getPluginManager().registerEvents(wbrl, plugin); - - // because the plugin loads "post world" - plugin.getServer().getWorlds().forEach(w -> { - wbrl.onWorldLoad(new WorldLoadEvent(w)); - }); - } - - if (TweaksConfig.getConfig().worldborderHide()) { - new WorldBorderHider().init(plugin); - } - } -} diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index fd93e94..b4aa0e0 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -4,8 +4,14 @@ # in the project root for the full license text. # +languageNotice = Language: %s (%s) +# Language name in your language +language = English +# Language name in English +languageEnglish = English + updateAvailableNotice = Available updates (%d): -pomodoroEndKick = Break time! Come back in 5 minutes. +pomodoroEndKick = Take a break! # Used in /updates updatesNotChecked = Not checked yet From ad36edd5cd95a20694bd654ccaf3446e18993685 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 13:36:03 +0100 Subject: [PATCH 09/89] Use the new class here --- .../eu/m724/tweaks/updater/UpdateChecker.java | 17 +++++++---------- .../eu/m724/tweaks/updater/UpdaterManager.java | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java index 61f0fb8..2687e32 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java @@ -6,9 +6,9 @@ package eu.m724.tweaks.updater; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; import eu.m724.tweaks.updater.cache.VersionedResource; -import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import java.io.FileOutputStream; @@ -19,18 +19,15 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletionException; -import java.util.logging.Logger; import java.util.stream.Collectors; public class UpdateChecker extends BukkitRunnable { private final Set resources; - private final Logger logger; static final Set availableUpdates = new HashSet<>(); static LocalTime lastChecked = null; - UpdateChecker(Plugin plugin, Set resources) { - this.logger = Logger.getLogger(plugin.getLogger().getName() + "." + getClass().getSimpleName()); + UpdateChecker(Set resources) { this.resources = resources; // TODO make a copy? } @@ -49,9 +46,9 @@ public class UpdateChecker extends BukkitRunnable { if (!versionedResource.equals(newResource)) { resources.remove(versionedResource); if (newResource.running() == null) { - logger.info("Unable to find installed version of %s".formatted(pluginName)); + DebugLogger.info("Unable to find installed version of %s".formatted(pluginName)); if (versionedResource.running() != null) { - logger.info("Did you downgrade %s? If so, clear cache".formatted(pluginName)); + DebugLogger.info("Did you downgrade %s? If so, clear cache".formatted(pluginName)); } } else { if (!newResource.running().equals(newResource.latest())) { @@ -62,7 +59,7 @@ public class UpdateChecker extends BukkitRunnable { resources.add(newResource); } } catch (CompletionException e) { - logger.severe("Unable to refresh %s: %s".formatted(pluginName, e.getMessage())); + DebugLogger.severe("Unable to refresh %s: %s".formatted(pluginName, e.getMessage())); } } } @@ -70,11 +67,11 @@ public class UpdateChecker extends BukkitRunnable { private void alert() { int n = availableUpdates.size(); if (n == 0) return; - logger.info(Language.getString("updateAvailableNotice", n)); + DebugLogger.info(Language.getString("updateAvailableNotice", n)); availableUpdates.stream() .map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label())) - .forEach(logger::info); + .forEach(DebugLogger::info); } @Override diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java index 6fa06b0..a535196 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java @@ -60,7 +60,7 @@ public class UpdaterManager { )).collect(Collectors.toSet()); - new UpdateChecker(plugin, versionedResources) + new UpdateChecker(versionedResources) .runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20); updatesCommand.setExecutor(new UpdaterCommands()); From e409d3e4dfbaa00628a5246e81bc7b5047c2a1aa Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 14:28:56 +0100 Subject: [PATCH 10/89] Knockback module --- .../java/eu/m724/tweaks/TweaksConfig.java | 12 +++- .../tweaks/knockback/KnockbackListener.java | 62 +++++++++++++++++++ src/main/resources/config.yml | 8 +++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 2c71c1f..b835162 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -9,6 +9,8 @@ package eu.m724.tweaks; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.Plugin; +import java.util.Map; + public record TweaksConfig( boolean metrics, boolean debug, @@ -53,7 +55,9 @@ public record TweaksConfig( String authDomain, boolean redstoneEnabled, - String redstoneListen + String redstoneListen, + + Map knockbackModifiers ) { public static final int CONFIG_VERSION = 1; private static TweaksConfig config; @@ -121,6 +125,9 @@ public record TweaksConfig( boolean redstoneEnabled = config.getBoolean("retstone.enabled"); String redstoneListen = config.getString("retstone.listen"); + // this is processed when initing + Map knockbackModifiers = config.getConfigurationSection("knockback").getValues(false); + TweaksConfig.config = new TweaksConfig( debug, metrics, locale, worldborderExpand, worldborderHide, @@ -134,7 +141,8 @@ public record TweaksConfig( hardcoreEnabled, hardcoreChance, sleepEnabled, sleepInstant, authEnabled, authForce, authHostname, - redstoneEnabled, redstoneListen + redstoneEnabled, redstoneListen, + knockbackModifiers ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java new file mode 100644 index 0000000..14e4764 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 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.knockback; + +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksConfig; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityKnockbackByEntityEvent; +import org.bukkit.plugin.Plugin; + +import java.util.HashMap; +import java.util.Map; + +public class KnockbackListener implements Listener { + private final Map modifiers = new HashMap<>(); + + public KnockbackListener(Plugin plugin) { + TweaksConfig.getConfig().knockbackModifiers().forEach((k, v) -> { + EntityType type; + double mod; + + String line = "(%s: %s)".formatted(k, v); + + if (v instanceof Double d) { + mod = d; + } else if (v instanceof Integer i) { + mod = i; + } else { + DebugLogger.warning("In " + line + " the value is not a number "); + return; + } + + try { + type = EntityType.valueOf(k); + } catch (IllegalArgumentException e) { + DebugLogger.warning("In" + line + " the key is not a valid entity type"); + DebugLogger.warning("Valid entity types: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html"); + return; + } + + if (mod == 1) return; + modifiers.put(type, mod); + }); + + if (!modifiers.isEmpty()) + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onEntityKnockbackByEntity(EntityKnockbackByEntityEvent event) { + var modifier = modifiers.get(event.getSourceEntity().getType()); + if (modifier != null) { + event.setFinalKnockback(event.getKnockback().multiply(modifier)); + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6f58952..6c0844a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -109,6 +109,14 @@ retstone: # This takes host:port, listens on UDP listen: 127.0.0.1:57931 +# Knockback dealt BY those entities is multiplied by value +# Entity must be one of https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html +# 1 means no change +knockback: + player: 0.7 + tnt: 5 + creeper: 0.7 + # Finally, thank you for downloading Tweaks724, I hope you enjoy! # Don't modify unless told to From 1cc787230cce389f6c6a4b0410c386532bf84785 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 15:35:36 +0100 Subject: [PATCH 11/89] Timer when pomodoro ends --- src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java | 3 +-- src/main/resources/strings.properties | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java index c88b920..3f28def 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java @@ -6,7 +6,6 @@ package eu.m724.tweaks.pomodoro; -import eu.m724.tweaks.Language; import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; @@ -38,7 +37,7 @@ public class PomodoroRunnable extends BukkitRunnable { if (remaining < -60 && force) { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { pomodoro.next(); - player.kickPlayer(Language.getString("pomodoroEndKick") + "\n" + Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now))); + player.kickPlayer(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now)).toLegacyText()); }); } } diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index b4aa0e0..2be019e 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -11,7 +11,6 @@ language = English languageEnglish = English updateAvailableNotice = Available updates (%d): -pomodoroEndKick = Take a break! # Used in /updates updatesNotChecked = Not checked yet From 69cb2ef9affa0f05dd790e56e14084288c2ac956 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 16:29:39 +0100 Subject: [PATCH 12/89] Move auth storage From "auth storage" to "storage/auth" --- src/main/java/eu/m724/tweaks/auth/AuthStorage.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/auth/AuthStorage.java b/src/main/java/eu/m724/tweaks/auth/AuthStorage.java index 3b08b6a..85fceed 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthStorage.java +++ b/src/main/java/eu/m724/tweaks/auth/AuthStorage.java @@ -19,12 +19,11 @@ public class AuthStorage { private final File keysDirectory; AuthStorage(Plugin plugin) { - File directory = new File(plugin.getDataFolder(), "auth storage"); + File directory = new File(plugin.getDataFolder(), "storage/auth"); this.playersDirectory = new File(directory, "players"); this.keysDirectory = new File(directory, "keys"); - directory.mkdir(); - keysDirectory.mkdir(); + keysDirectory.mkdirs(); playersDirectory.mkdir(); } From 9e4125dd4ecbb077c435a421cd0ac8c67073ca86 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 16:37:32 +0100 Subject: [PATCH 13/89] Move chat storage From "rooms" to "storage/rooms" --- .../java/eu/m724/tweaks/chat/ChatManager.java | 9 +++---- .../eu/m724/tweaks/chat/ChatRoomLoader.java | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/chat/ChatManager.java b/src/main/java/eu/m724/tweaks/chat/ChatManager.java index 89b1ff1..04d1a84 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatManager.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatManager.java @@ -19,7 +19,6 @@ import org.bukkit.plugin.Plugin; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Objects; public class ChatManager { private final Plugin plugin; @@ -75,7 +74,7 @@ public class ChatManager { if (id.equals(defaultRoom)) { chatRoom = new ChatRoom(defaultRoom, null, null); } else { - chatRoom = ChatRoomLoader.load(plugin, id); + chatRoom = ChatRoomLoader.load(id); } roomIdMap.put(id, chatRoom); } @@ -172,17 +171,17 @@ public class ChatManager { throw new ChatRoomExistsException(); ChatRoom chatRoom = new ChatRoom(id, password, owner); - ChatRoomLoader.save(plugin, chatRoom); + ChatRoomLoader.save(chatRoom); return chatRoom; } void saveChatRoom(ChatRoom chatRoom) throws IOException { - ChatRoomLoader.save(plugin, chatRoom); + ChatRoomLoader.save(chatRoom); } public void deleteChatRoom(ChatRoom chatRoom) { roomIdMap.remove(chatRoom.id); - ChatRoomLoader.getFile(plugin, chatRoom.id).delete(); + ChatRoomLoader.getFile(chatRoom.id).delete(); chatRoom.players.forEach(player -> setPlayerChatRoom(getById(defaultRoom), player)); } diff --git a/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java b/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java index f2c73fa..a160311 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java @@ -13,23 +13,25 @@ import org.bukkit.plugin.Plugin; import java.io.File; import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.UUID; public class ChatRoomLoader { + private static File chatRoomsDir; + + static void init(Plugin plugin) { + chatRoomsDir = new File(plugin.getDataFolder(), "storage/rooms"); + chatRoomsDir.mkdirs(); + } + /** * Get the file of persistent storage of a chat room * @return the file or null if ID is invalid */ - static File getFile(Plugin plugin, String id) { - Path chatRoomsPath = Paths.get(plugin.getDataFolder().getPath(), "rooms"); - chatRoomsPath.toFile().mkdirs(); - + static File getFile(String id) { if (validateId(id) != 0) throw new RuntimeException("Invalid id: " + id); - return Paths.get(chatRoomsPath.toFile().getPath(), id + ".yml").toFile(); + return new File(chatRoomsDir, id + ".yml"); } /** @@ -62,8 +64,8 @@ public class ChatRoomLoader { * @param id the id of the chat room * @return the chat room or null if no such chat room */ - static ChatRoom load(Plugin plugin, String id) { - File chatRoomFile = getFile(plugin, id); + static ChatRoom load(String id) { + File chatRoomFile = getFile(id); if (!chatRoomFile.exists()) return null; YamlConfiguration configuration = YamlConfiguration.loadConfiguration(chatRoomFile); @@ -89,14 +91,15 @@ public class ChatRoomLoader { * * @throws IOException if saving failed */ - static void save(Plugin plugin, ChatRoom chatRoom) throws IOException { + static void save(ChatRoom chatRoom) throws IOException { YamlConfiguration configuration = new YamlConfiguration(); configuration.set("password", chatRoom.password); configuration.set("color", chatRoom.color.getName()); + // TODO consider just making this str to make it easier configuration.set("owner.msb", chatRoom.owner.getUniqueId().getMostSignificantBits()); configuration.set("owner.lsb", chatRoom.owner.getUniqueId().getLeastSignificantBits()); - File chatRoomFile = getFile(plugin, chatRoom.id); + File chatRoomFile = getFile(chatRoom.id); configuration.save(chatRoomFile); } } From 3a6d1366abc1289fa0bb5c6d116a54a0ece7f858 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 16:38:33 +0100 Subject: [PATCH 14/89] Bump config version because we're getting tons of changes --- src/main/java/eu/m724/tweaks/TweaksConfig.java | 5 +++-- src/main/resources/config.yml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index b835162..57530df 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -59,7 +59,7 @@ public record TweaksConfig( Map knockbackModifiers ) { - public static final int CONFIG_VERSION = 1; + public static final int CONFIG_VERSION = 2; private static TweaksConfig config; public static TweaksConfig getConfig() { @@ -72,10 +72,11 @@ public record TweaksConfig( int configVersion = config.getInt("magic number don't modify this", 0); RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION)); + if (configVersion == 0) { throw exception; } else if (configVersion > CONFIG_VERSION) { - throw new RuntimeException("Please follow update instructions", exception); + throw new RuntimeException("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception); } else if (configVersion < CONFIG_VERSION) { throw new RuntimeException("Did you downgrade the plugin? Remove config.yml and let the plugin re-create it", exception); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6c0844a..cd0a604 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -120,4 +120,4 @@ knockback: # Finally, thank you for downloading Tweaks724, I hope you enjoy! # Don't modify unless told to -magic number don't modify this: 1 \ No newline at end of file +magic number don't modify this: 2 \ No newline at end of file From 6153da89a162eed8b979980dd660852381da7443 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 17:01:49 +0100 Subject: [PATCH 15/89] Fix wrong tip if wrong config version --- src/main/java/eu/m724/tweaks/TweaksConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 57530df..3a10a27 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -75,9 +75,9 @@ public record TweaksConfig( if (configVersion == 0) { throw exception; - } else if (configVersion > CONFIG_VERSION) { - throw new RuntimeException("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception); } else if (configVersion < CONFIG_VERSION) { + throw new RuntimeException("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception); + } else if (configVersion > CONFIG_VERSION) { throw new RuntimeException("Did you downgrade the plugin? Remove config.yml and let the plugin re-create it", exception); } From c92d4429da302bc8f2c0d38d342756a7d00741e8 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 17:04:39 +0100 Subject: [PATCH 16/89] Also move updater cache From "cache/updater" to "storage/cache/updater" --- src/main/java/eu/m724/tweaks/updater/UpdaterManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java index a535196..9bb1904 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java @@ -28,7 +28,7 @@ public class UpdaterManager { public UpdaterManager(Plugin plugin) { this.plugin = plugin; - cacheFile = new File(plugin.getDataFolder(), "cache/updater"); + cacheFile = new File(plugin.getDataFolder(), "storage/updater"); } public void init(PluginCommand updatesCommand){ From 1acfcd273d25e27b6a1cbe2ae6d82d4aa7dbc55b Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 17:07:51 +0100 Subject: [PATCH 17/89] Forgot to enable knockback module --- src/main/java/eu/m724/tweaks/TweaksPlugin.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index f1e705e..7c5e238 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -14,6 +14,7 @@ import eu.m724.tweaks.door.DoorKnockListener; import eu.m724.tweaks.door.DoorOpenListener; import eu.m724.tweaks.full.FullListener; import eu.m724.tweaks.hardcore.HardcoreManager; +import eu.m724.tweaks.knockback.KnockbackListener; import eu.m724.tweaks.motd.MotdManager; import eu.m724.tweaks.ping.F3NameListener; import eu.m724.tweaks.ping.PingChecker; @@ -125,6 +126,9 @@ public class TweaksPlugin extends MStatsPlugin { new RedstoneManager(this).init(getCommand("retstone")); } + DebugLogger.fine("Enabling Knockback"); + new KnockbackListener(this); + /* end modules */ if (config.metrics()) { From 812b16e4be590aa05f50d06af1a7ce0f574abb1d Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 18:15:09 +0100 Subject: [PATCH 18/89] Click to copy repeater Also added translation for copying --- .../java/eu/m724/tweaks/auth/AuthCommands.java | 3 ++- .../m724/tweaks/redstone/RedstoneListener.java | 16 ++++++++++++++-- src/main/resources/strings.properties | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/auth/AuthCommands.java b/src/main/java/eu/m724/tweaks/auth/AuthCommands.java index 5463fb4..d33767c 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthCommands.java +++ b/src/main/java/eu/m724/tweaks/auth/AuthCommands.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.auth; +import eu.m724.tweaks.Language; import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; @@ -50,7 +51,7 @@ public class AuthCommands implements CommandExecutor { .underlined(true) .color(ChatColor.GRAY) .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, hostname)) - .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to copy"))) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToCopy")))) .build(); sender.spigot().sendMessage(component); } else { diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java index 1883a49..7cd1ffd 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java @@ -7,6 +7,12 @@ package eu.m724.tweaks.redstone; import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.Language; +import net.md_5.bungee.api.ChatColor; +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.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; @@ -45,13 +51,19 @@ public class RedstoneListener implements Listener { @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if (event.getClickedBlock() == null) return; + if (!event.getPlayer().isSneaking()) return; var id = redstoneRepeaters.getId(event.getClickedBlock()); if (id == Integer.MIN_VALUE) return; // TODO find a less lame way of showing ID - event.getPlayer().sendMessage("Repeater ID: " + id); + var component = new ComponentBuilder("Repeater ID: ").color(ChatColor.GOLD) + .append(String.valueOf(id)).color(ChatColor.AQUA) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToCopy")))) + .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.valueOf(id))) + .build(); + + event.getPlayer().spigot().sendMessage(component); } @EventHandler diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 2be019e..41529fa 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -30,4 +30,6 @@ authKickWrongKey = You're connecting to the wrong server address. You must conne # If force is enabled and player is not registered. Changing this reveals you're using this plugin authKickUnregistered = You are not whitelisted on this server! -retstoneBlockItem = Online redstone block \ No newline at end of file +retstoneBlockItem = Online redstone block + +clickToCopy = Click to copy to clipboard \ No newline at end of file From 225adf035459d274e0a9af5c1d4f2b418a1038cb Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 18:39:34 +0100 Subject: [PATCH 19/89] Remove debug printlns --- .../m724/tweaks/redstone/RedstoneManager.java | 2 +- .../tweaks/redstone/RedstoneRepeaters.java | 30 +++++++++++-------- .../{Store.java => RedstoneStore.java} | 16 ++++++---- 3 files changed, 28 insertions(+), 20 deletions(-) rename src/main/java/eu/m724/tweaks/redstone/{Store.java => RedstoneStore.java} (82%) diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java index d4491d5..437dfc1 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java @@ -29,7 +29,7 @@ public class RedstoneManager { } public void init(PluginCommand command) { - Store.init(plugin); + RedstoneStore.init(plugin); plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneRepeaters), plugin); command.setExecutor(new RedstoneCommands(redstoneRepeaters)); diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java index 77b1a77..c554379 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java @@ -8,6 +8,7 @@ package eu.m724.tweaks.redstone; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; import org.bukkit.Location; import org.bukkit.Material; @@ -65,7 +66,7 @@ public class RedstoneRepeaters { repeatersById.put(repeaterId, block.getLocation()); block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId)); - Store.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0); + RedstoneStore.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0); return repeaterId; } @@ -79,7 +80,7 @@ public class RedstoneRepeaters { if (location == null) return; repeatersByPower.remove(repeaterId); - Store.getInstance().deleteSavedRepeaterData(location); + RedstoneStore.getInstance().deleteSavedRepeaterData(location); } /* Get functions */ @@ -89,7 +90,7 @@ public class RedstoneRepeaters { // if not, we're not loading because it's loaded as the block is var loc = repeatersById.get(repeaterId); if (loc == null) { - System.err.println("Delete because no loc"); + DebugLogger.fine("isValid: Delete because no loc"); delete(repeaterId); return false; } @@ -101,6 +102,7 @@ public class RedstoneRepeaters { // check if the block is correct type if (loc.getBlock().getType() != Material.DAYLIGHT_DETECTOR) { + DebugLogger.fine("isValid: Delete because not sensor"); delete(repeaterId); return false; } @@ -108,7 +110,7 @@ public class RedstoneRepeaters { // check if the block has the same ID bound var meta = loc.getBlock().getMetadata("rid"); if (meta.isEmpty() || meta.getFirst().asInt() != repeaterId) { - System.err.println("Delete because no meta"); + DebugLogger.fine("isValid: Delete because no meta"); delete(repeaterId); return false; } @@ -126,7 +128,7 @@ public class RedstoneRepeaters { if (id == null) { // not in memory, check if repeater - var d = Store.getInstance().getSavedRepeaterData(block.getLocation()); + var d = RedstoneStore.getInstance().getSavedRepeaterData(block.getLocation()); if (d == null) { block.setMetadata("rid", new FixedMetadataValue(plugin, Integer.MIN_VALUE)); @@ -153,12 +155,13 @@ public class RedstoneRepeaters { var storedId = location.getBlock().getMetadata("rid").getFirst().asInt(); if (storedId != repeaterId) { - System.out.println("retrieved but not exitt"); + DebugLogger.fine("attempted retrieve, but doesn't exist, deleting " + repeaterId); delete(repeaterId); return null; } - System.out.println("retrieved exist " + repeaterId); + DebugLogger.fine("retrieved " + repeaterId); + return location.getBlock(); } @@ -170,20 +173,21 @@ public class RedstoneRepeaters { block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); - System.out.println("Okay I got in power" + block.getBlockPower()); - return (byte) block.getBlockPower(); + var power = (byte) block.getBlockPower(); + DebugLogger.fine("Got " + repeaterId + " receives " + power); + return power; } byte getOutboundPower(int repeaterId) { var block = getBlock(repeaterId); if (block == null) return -1; - System.out.println("Okay I got out power" + repeatersByPower.get(repeaterId)); - return repeatersByPower.getOrDefault(repeaterId, (byte) 0); + var power = repeatersByPower.getOrDefault(repeaterId, (byte) 0); + DebugLogger.fine("Got " + repeaterId + " outputs " + power); + return power; } void setPower(int repeaterId, byte power) { - System.out.println(power); if (power < 0 || power > 15) throw new IllegalArgumentException("Power should be 0-15, but is " + power); @@ -197,6 +201,6 @@ public class RedstoneRepeaters { block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); - System.out.println("Okay I set power"); + DebugLogger.fine("Set power of " + repeaterId + " to " + power); } } \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/redstone/Store.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java similarity index 82% rename from src/main/java/eu/m724/tweaks/redstone/Store.java rename to src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java index d9d8ff8..cd24665 100644 --- a/src/main/java/eu/m724/tweaks/redstone/Store.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java @@ -7,6 +7,7 @@ package eu.m724.tweaks.redstone; import com.google.common.primitives.Ints; +import eu.m724.tweaks.DebugLogger; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Location; import org.bukkit.plugin.Plugin; @@ -15,23 +16,23 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; -public class Store { - private static Store INSTANCE; +public class RedstoneStore { + private static RedstoneStore INSTANCE; private final Plugin plugin; private final File directory; - private Store(Plugin plugin) { + private RedstoneStore(Plugin plugin) { this.plugin = plugin; this.directory = new File(plugin.getDataFolder(), "storage/redstone"); directory.mkdirs(); } static void init(Plugin plugin) { - INSTANCE = new Store(plugin); + INSTANCE = new RedstoneStore(plugin); } - static Store getInstance() { + static RedstoneStore getInstance() { return INSTANCE; } @@ -51,12 +52,13 @@ public class Store { var repeaterId = Ints.fromByteArray(bytes) & ~0xF; var powerLevel = (byte) (bytes[3] & 0xF); + DebugLogger.fine("load " + location + " " + repeaterId + " " + powerLevel); + return Pair.of(repeaterId, powerLevel); } void saveRepeaterData(Location location, int repeaterId, byte powerLevel) { var file = getFile(location); - System.out.println(file); byte[] bytes = Ints.toByteArray((repeaterId & ~0xF) | (powerLevel & 0xF)); try { @@ -64,6 +66,8 @@ public class Store { } catch (IOException e) { throw new RuntimeException("Saving repeater data", e); } + + DebugLogger.fine("save " + location + " " + repeaterId + " " + powerLevel); } void deleteSavedRepeaterData(Location location) { From c0b85870e01a5cbe6340c31d05f2556cc051e52c Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 21:35:44 +0100 Subject: [PATCH 20/89] Rename to gateway, add crafting, some other changes --- README.md | 6 +- RETSTONE.md | 17 +++++- .../eu/m724/tweaks/redstone/GatewayItem.java | 50 +++++++++++++++++ .../tweaks/redstone/RedstoneCommands.java | 9 +-- ...neRepeaters.java => RedstoneGateways.java} | 55 +++++-------------- .../tweaks/redstone/RedstoneListener.java | 39 ++++++++----- .../m724/tweaks/redstone/RedstoneManager.java | 33 ++++++----- .../redstone/RedstoneStateUpdateRunnable.java | 14 ++--- .../m724/tweaks/redstone/RedstoneStore.java | 16 +++--- src/main/resources/config.yml | 2 +- src/main/resources/plugin.yml | 4 ++ src/main/resources/strings.properties | 2 +- 12 files changed, 152 insertions(+), 95 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/redstone/GatewayItem.java rename src/main/java/eu/m724/tweaks/redstone/{RedstoneRepeaters.java => RedstoneGateways.java} (73%) diff --git a/README.md b/README.md index 4aefca5..1e49879 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,11 @@ Issue messages that the player needs to read to keep playing, and that make an a `/emergencyalerts` (`tweaks724.emergencyalerts`) ### Remote redstone -Control redstone remotely +Adds a "gateway" item that are controlled over internet. \ +[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/RETSTONE.md) + +### Knockback +Control knockback dealt by entities ### Utility commands diff --git a/RETSTONE.md b/RETSTONE.md index 8f299d8..d33195b 100644 --- a/RETSTONE.md +++ b/RETSTONE.md @@ -3,8 +3,21 @@ See [retstone.py](retstone.py) for usage example ### Glossary -repeaters - the blocks which allow to interact with redstone over internet \ -packet - a bunch of bytes sent over the internet, that do something with a single repeater +gateways - the blocks (daylight detector) that read or emit redstone with a specified power, controlled with UDP packets \ +packet - a bunch of bytes sent over the internet, that do something with a specified gateway + +### Crafting + +To craft a gateway, combine: +- nether star +- ender chest +- chorus flower +- daylight detector + +### Usage +Each gateway has an ID assigned. To view it, shift right-click a gateway. + +To destroy a gateway, use silk touch. ### How it works A packet is int / 4 bytes / 32 bits diff --git a/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java new file mode 100644 index 0000000..5d24f05 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 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.redstone; + +import eu.m724.tweaks.Language; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.plugin.Plugin; + +public class GatewayItem { + private final NamespacedKey gatewayKey; + + public GatewayItem(Plugin plugin) { + this.gatewayKey = new NamespacedKey(plugin, "gateway"); + + var recipe = new ShapelessRecipe(gatewayKey, itemStack()); + recipe.addIngredient(Material.NETHER_STAR); + recipe.addIngredient(Material.ENDER_CHEST); + recipe.addIngredient(Material.CHORUS_FLOWER); + recipe.addIngredient(Material.DAYLIGHT_DETECTOR); + plugin.getServer().addRecipe(recipe); + } + + public ItemStack itemStack() { + var itemStack = new ItemStack(Material.DAYLIGHT_DETECTOR); + var meta = itemStack.getItemMeta(); + + meta.setItemName(Language.getString("redstoneGatewayItem")); + meta.getPersistentDataContainer().set(gatewayKey, PersistentDataType.BOOLEAN, true); + meta.setEnchantmentGlintOverride(true); + + itemStack.setItemMeta(meta); + return itemStack; + } + + public boolean isGateway(ItemStack itemStack) { + var meta = itemStack.getItemMeta(); + if (meta == null) return false; + var value = meta.getPersistentDataContainer().get(gatewayKey, PersistentDataType.BOOLEAN); + + return value != null; + } +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java index 45522f0..f1c6b28 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java @@ -14,10 +14,10 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; public class RedstoneCommands implements CommandExecutor { - private final RedstoneRepeaters redstoneRepeaters; + private final GatewayItem gatewayItem; - public RedstoneCommands(RedstoneRepeaters redstoneRepeaters) { - this.redstoneRepeaters = redstoneRepeaters; + public RedstoneCommands(GatewayItem gatewayItem) { + this.gatewayItem = gatewayItem; } @@ -41,8 +41,9 @@ public class RedstoneCommands implements CommandExecutor { } } - var itemStack = redstoneRepeaters.give(); + var itemStack = gatewayItem.itemStack(); player.getInventory().addItem(itemStack); + sender.sendMessage("Given to " + player.getName()); } } else { sender.sendMessage("Argument needed"); diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java similarity index 73% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java rename to src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java index c554379..d7ae10f 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneRepeaters.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java @@ -9,53 +9,26 @@ package eu.m724.tweaks.redstone; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.Language; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.Particle; import org.bukkit.block.Block; import org.bukkit.block.data.AnaloguePowerable; -import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.persistence.PersistentDataType; import org.bukkit.plugin.Plugin; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; -public class RedstoneRepeaters { +public class RedstoneGateways { private final Plugin plugin; - private final NamespacedKey repeaterKey; - private final BiMap repeatersById = HashBiMap.create(); - private final Map repeatersByPower = new HashMap<>(); + private final BiMap gatewaysById = HashBiMap.create(); + private final Map gatewaysByPower = new HashMap<>(); - public RedstoneRepeaters(Plugin plugin) { + public RedstoneGateways(Plugin plugin) { this.plugin = plugin; - this.repeaterKey = new NamespacedKey(plugin, "repeater"); - } - - /* Item functions */ - - public ItemStack give() { - var itemStack = new ItemStack(Material.DAYLIGHT_DETECTOR); - var meta = itemStack.getItemMeta(); - - meta.setItemName(Language.getString("retstoneBlockItem")); - meta.getPersistentDataContainer().set(repeaterKey, PersistentDataType.BOOLEAN, true); - meta.setEnchantmentGlintOverride(true); - - itemStack.setItemMeta(meta); - return itemStack; - } - - public boolean isRepeater(ItemStack itemStack) { - var meta = itemStack.getItemMeta(); - if (meta == null) return false; - var value = meta.getPersistentDataContainer().get(repeaterKey, PersistentDataType.BOOLEAN); - return value != null; } /* Event */ @@ -63,7 +36,7 @@ public class RedstoneRepeaters { int onPlace(Block block) { var repeaterId = ThreadLocalRandom.current().nextInt() & 0x7FFFFFF0; - repeatersById.put(repeaterId, block.getLocation()); + gatewaysById.put(repeaterId, block.getLocation()); block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId)); RedstoneStore.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0); @@ -76,9 +49,9 @@ public class RedstoneRepeaters { } void delete(int repeaterId) { - var location = repeatersById.remove(repeaterId); + var location = gatewaysById.remove(repeaterId); if (location == null) return; - repeatersByPower.remove(repeaterId); + gatewaysByPower.remove(repeaterId); RedstoneStore.getInstance().deleteSavedRepeaterData(location); } @@ -88,7 +61,7 @@ public class RedstoneRepeaters { private boolean isValid(int repeaterId) { // check if there's a repeater with such ID stored // if not, we're not loading because it's loaded as the block is - var loc = repeatersById.get(repeaterId); + var loc = gatewaysById.get(repeaterId); if (loc == null) { DebugLogger.fine("isValid: Delete because no loc"); delete(repeaterId); @@ -124,7 +97,7 @@ public class RedstoneRepeaters { return id; } - var id = repeatersById.inverse().get(block.getLocation()); + var id = gatewaysById.inverse().get(block.getLocation()); if (id == null) { // not in memory, check if repeater @@ -138,8 +111,8 @@ public class RedstoneRepeaters { id = d.getKey(); block.setMetadata("rid", new FixedMetadataValue(plugin, id)); - repeatersById.put(id, block.getLocation()); - repeatersByPower.put(id, d.getValue()); + gatewaysById.put(id, block.getLocation()); + gatewaysByPower.put(id, d.getValue()); } if (!isValid(id)) return Integer.MIN_VALUE; @@ -148,7 +121,7 @@ public class RedstoneRepeaters { } Block getBlock(int repeaterId) { - var location = repeatersById.get(repeaterId); + var location = gatewaysById.get(repeaterId); if (location == null) return null; if (!isValid(repeaterId)) return null; @@ -182,7 +155,7 @@ public class RedstoneRepeaters { var block = getBlock(repeaterId); if (block == null) return -1; - var power = repeatersByPower.getOrDefault(repeaterId, (byte) 0); + var power = gatewaysByPower.getOrDefault(repeaterId, (byte) 0); DebugLogger.fine("Got " + repeaterId + " outputs " + power); return power; } @@ -196,7 +169,7 @@ public class RedstoneRepeaters { var data = (AnaloguePowerable) block.getBlockData(); - repeatersByPower.put(repeaterId, power); + gatewaysByPower.put(repeaterId, power); data.setPower(power); block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3); diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java index 7cd1ffd..bff3c1e 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java @@ -13,6 +13,7 @@ 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.enchantments.Enchantment; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; @@ -22,30 +23,37 @@ import org.bukkit.event.block.BlockRedstoneEvent; import org.bukkit.event.player.PlayerInteractEvent; public class RedstoneListener implements Listener { - private final RedstoneRepeaters redstoneRepeaters; + private final RedstoneGateways redstoneGateways; + private final GatewayItem gatewayItem; - public RedstoneListener(RedstoneRepeaters redstoneRepeaters) { - this.redstoneRepeaters = redstoneRepeaters; + public RedstoneListener(RedstoneGateways redstoneGateways, GatewayItem gatewayItem) { + this.redstoneGateways = redstoneGateways; + this.gatewayItem = gatewayItem; } @EventHandler public void onBlockPlace(BlockPlaceEvent event) { - if (!redstoneRepeaters.isRepeater(event.getItemInHand())) return; + if (!gatewayItem.isGateway(event.getItemInHand())) return; var block = event.getBlockPlaced(); - var id = redstoneRepeaters.onPlace(block); + var id = redstoneGateways.onPlace(block); - DebugLogger.fine("Repeater placed: " + id); + DebugLogger.fine("Gateway placed: " + id); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { - var id = redstoneRepeaters.getId(event.getBlock()); + var id = redstoneGateways.getId(event.getBlock()); if (id == Integer.MIN_VALUE) return; - redstoneRepeaters.onBreak(id); + redstoneGateways.onBreak(id); - DebugLogger.fine("Repeater broken: " + id); + if (event.getPlayer().getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH)) { + event.setDropItems(false); + event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), gatewayItem.itemStack()); + } + + DebugLogger.fine("Gateway broken: " + id); } @EventHandler @@ -53,28 +61,31 @@ public class RedstoneListener implements Listener { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (!event.getPlayer().isSneaking()) return; - var id = redstoneRepeaters.getId(event.getClickedBlock()); + var id = redstoneGateways.getId(event.getClickedBlock()); if (id == Integer.MIN_VALUE) return; // TODO find a less lame way of showing ID - var component = new ComponentBuilder("Repeater ID: ").color(ChatColor.GOLD) + var component = new ComponentBuilder("Gateway ID: ").color(ChatColor.GOLD) .append(String.valueOf(id)).color(ChatColor.AQUA) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToCopy")))) .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.valueOf(id))) .build(); event.getPlayer().spigot().sendMessage(component); + + // cancel block place + event.setCancelled(true); } @EventHandler public void onBlockRedstone(BlockRedstoneEvent event) { var block = event.getBlock(); - var id = redstoneRepeaters.getId(block); + var id = redstoneGateways.getId(block); if (id == Integer.MIN_VALUE) return; - event.setNewCurrent(redstoneRepeaters.getOutboundPower(id)); + event.setNewCurrent(redstoneGateways.getOutboundPower(id)); - DebugLogger.fine("Repeater redstone event: " + id); + DebugLogger.fine("Gateway redstone event: " + id); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java index 437dfc1..2dde5bc 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java @@ -18,23 +18,25 @@ import java.util.function.Consumer; public class RedstoneManager { private final Plugin plugin; - private final RedstoneRepeaters redstoneRepeaters; + private final RedstoneGateways redstoneGateways; private DatagramSocket socket; private RedstoneStateUpdateRunnable runnable; + public RedstoneManager(Plugin plugin) { this.plugin = plugin; - this.redstoneRepeaters = new RedstoneRepeaters(plugin); + this.redstoneGateways = new RedstoneGateways(plugin); } public void init(PluginCommand command) { RedstoneStore.init(plugin); + var gatewayItem = new GatewayItem(plugin); - plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneRepeaters), plugin); - command.setExecutor(new RedstoneCommands(redstoneRepeaters)); + plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneGateways, gatewayItem), plugin); + command.setExecutor(new RedstoneCommands(gatewayItem)); - this.runnable = new RedstoneStateUpdateRunnable(redstoneRepeaters); + this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways); this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":"); @@ -50,6 +52,7 @@ public class RedstoneManager { } catch (SocketException e) { throw new RuntimeException("Starting socket", e); } + } private void initSocket(SocketAddress bindAddress) throws SocketException { @@ -70,15 +73,15 @@ public class RedstoneManager { boolean write = (buf[0] >> 7 & 1) == 1; byte data = (byte) (buf[3] & 0xF); - int repeaterId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0); + int gatewayId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0); if (write) { - enqueueUpdate(repeaterId, data); + enqueueUpdate(gatewayId, data); } else { var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress()); - enqueueRetrieve(repeaterId, value -> { - DebugLogger.fine("Retrieved for " + repeaterId + " power " + value); + enqueueRetrieve(gatewayId, value -> { + DebugLogger.fine("Retrieved for " + gatewayId + " power " + value); newPacket.setData(new byte[] { (byte) Math.max(value, 0) }); try { @@ -92,13 +95,13 @@ public class RedstoneManager { }); } - private void enqueueUpdate(int repeaterId, byte power) { - DebugLogger.fine("Update enqueued " + repeaterId + " " + power); - runnable.enqueueUpdate(repeaterId, power); + private void enqueueUpdate(int gatewayId, byte power) { + DebugLogger.fine("Update enqueued " + gatewayId + " " + power); + runnable.enqueueUpdate(gatewayId, power); } - private void enqueueRetrieve(int repeaterId, Consumer consumer) { - DebugLogger.fine("Retrieve enqueued " + repeaterId); - runnable.enqueueRetrieve(repeaterId, consumer); + private void enqueueRetrieve(int gatewayId, Consumer consumer) { + DebugLogger.fine("Retrieve enqueued " + gatewayId); + runnable.enqueueRetrieve(gatewayId, consumer); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java index 4368f68..f036f49 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java @@ -16,14 +16,14 @@ public class RedstoneStateUpdateRunnable extends BukkitRunnable { private Map updateQueue = new HashMap<>(); private Map> retrieveQueue = new HashMap<>(); - private final RedstoneRepeaters redstoneRepeaters; + private final RedstoneGateways redstoneGateways; - RedstoneStateUpdateRunnable(RedstoneRepeaters redstoneRepeaters) { - this.redstoneRepeaters = redstoneRepeaters; + RedstoneStateUpdateRunnable(RedstoneGateways redstoneGateways) { + this.redstoneGateways = redstoneGateways; } - void enqueueUpdate(int repeaterId, byte power) { - updateQueue.put(repeaterId, power); + void enqueueUpdate(int gatewayId, byte power) { + updateQueue.put(gatewayId, power); } void enqueueRetrieve(int repeaterId, Consumer consumer) { @@ -38,7 +38,7 @@ public class RedstoneStateUpdateRunnable extends BukkitRunnable { var retrieveQueue = this.retrieveQueue; this.retrieveQueue = new HashMap<>(); - updateQueue.forEach((key, value) -> redstoneRepeaters.setPower(key, value)); - retrieveQueue.forEach((key, value) -> value.accept(redstoneRepeaters.getInboundPower(key))); + updateQueue.forEach((key, value) -> redstoneGateways.setPower(key, value)); + retrieveQueue.forEach((key, value) -> value.accept(redstoneGateways.getInboundPower(key))); } } diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java index cd24665..8c812ea 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java @@ -19,11 +19,9 @@ import java.nio.file.Files; public class RedstoneStore { private static RedstoneStore INSTANCE; - private final Plugin plugin; private final File directory; private RedstoneStore(Plugin plugin) { - this.plugin = plugin; this.directory = new File(plugin.getDataFolder(), "storage/redstone"); directory.mkdirs(); } @@ -46,20 +44,20 @@ public class RedstoneStore { // TODO read just 4 bytes bytes = Files.readAllBytes(file.toPath()); } catch (IOException e) { - throw new RuntimeException("Loading saved repeater data", e); + throw new RuntimeException("Loading saved gateway data", e); } - var repeaterId = Ints.fromByteArray(bytes) & ~0xF; + var gatewayId = Ints.fromByteArray(bytes) & ~0xF; var powerLevel = (byte) (bytes[3] & 0xF); - DebugLogger.fine("load " + location + " " + repeaterId + " " + powerLevel); + DebugLogger.fine("load " + location + " " + gatewayId + " " + powerLevel); - return Pair.of(repeaterId, powerLevel); + return Pair.of(gatewayId, powerLevel); } - void saveRepeaterData(Location location, int repeaterId, byte powerLevel) { + void saveRepeaterData(Location location, int gatewayId, byte powerLevel) { var file = getFile(location); - byte[] bytes = Ints.toByteArray((repeaterId & ~0xF) | (powerLevel & 0xF)); + byte[] bytes = Ints.toByteArray((gatewayId & ~0xF) | (powerLevel & 0xF)); try { Files.write(file.toPath(), bytes); @@ -67,7 +65,7 @@ public class RedstoneStore { throw new RuntimeException("Saving repeater data", e); } - DebugLogger.fine("save " + location + " " + repeaterId + " " + powerLevel); + DebugLogger.fine("save " + location + " " + gatewayId + " " + powerLevel); } void deleteSavedRepeaterData(Location location) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index cd0a604..bcf91fa 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -103,7 +103,7 @@ auth: # The domain of the server. Doesn't do anything other than showing in /tauth new domain: "replace.me" -# Adds blocks which allow to interact with redstone over internet +# Adds gateways emitting redstone, controlled over internet retstone: enabled: true # This takes host:port, listens on UDP diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f018798..e96250e 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -35,6 +35,8 @@ commands: description: Send emergency alert permission: tweaks724.emergencyalert retstone: + description: Retstone commands + permission: tweaks724.retstone permissions: tweaks724: @@ -50,4 +52,6 @@ permissions: default: op emergencyalert: default: op + retstone: + default: op diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 41529fa..550c4f8 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -30,6 +30,6 @@ authKickWrongKey = You're connecting to the wrong server address. You must conne # If force is enabled and player is not registered. Changing this reveals you're using this plugin authKickUnregistered = You are not whitelisted on this server! -retstoneBlockItem = Online redstone block +redstoneGatewayItem = Redstone gateway clickToCopy = Click to copy to clipboard \ No newline at end of file From ba097e7f1902a23a114962300a63438806e81e2d Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 21:36:25 +0100 Subject: [PATCH 21/89] [maven-release-plugin] prepare release tweaks-0.1.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 384a528..02650da 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.10-SNAPSHOT + 0.1.10 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.10 \ No newline at end of file From 83da4ae872ebac3a4e15c97ce3b485fa4624c328 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 31 Dec 2024 21:36:27 +0100 Subject: [PATCH 22/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 02650da..4427771 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.10 + 0.1.11-SNAPSHOT 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.10 + HEAD \ No newline at end of file From 38a0cc331d58929d4f9a807cd234c6f9a022291f Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 11:28:52 +0100 Subject: [PATCH 23/89] Clarify some --- RETSTONE.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RETSTONE.md b/RETSTONE.md index d33195b..78d96ad 100644 --- a/RETSTONE.md +++ b/RETSTONE.md @@ -32,11 +32,14 @@ action bits 2-28 of repeater id - payload: power level if writing If writing, no response \ -If reading, response is the power level, or 0 if not powered or no repeater with that ID +If reading, response is the power level, or 0 if not powered or no repeater with that ID (or not loaded) Reading powers the block down of course \ BUT you should power it down (or read), wait some, and then read again +**WARNING** the socket is not ratelimited or protected in any way. \ +Though it should be hard to bruteforce, because there's no feedback + ### Retstone **Network** translates to **reto** in Esperanto \ From a157943187996f8f05e35f163c4afb9973d3f372 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 12:10:42 +0100 Subject: [PATCH 24/89] JSON in motd --- .../java/eu/m724/tweaks/motd/MotdManager.java | 22 ++++++++++++++++--- src/main/resources/motd sets/example.txt | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/motd/MotdManager.java b/src/main/java/eu/m724/tweaks/motd/MotdManager.java index 1748ae8..0ac9c79 100644 --- a/src/main/java/eu/m724/tweaks/motd/MotdManager.java +++ b/src/main/java/eu/m724/tweaks/motd/MotdManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -11,6 +11,9 @@ import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.*; import com.comphenix.protocol.reflect.StructureModifier; import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; import eu.m724.tweaks.TweaksPlugin; import net.md_5.bungee.api.chat.TextComponent; @@ -64,8 +67,21 @@ public class MotdManager { // MOTDs are split with an empty line motds = Arrays.stream(fileContent.split("\n\n")) - .map(s -> { - JsonElement json = ComponentSerializer.toJson(TextComponent.fromLegacy(s.strip())); + .map(entry -> { + entry = entry.strip(); + JsonElement json = null; + + try { + json = JsonParser.parseString(entry); + DebugLogger.fine("JSON line: " + entry); + } catch (JsonParseException e) { + DebugLogger.fine("Not a JSON line: " + entry); + } + + if (json == null) { + json = ComponentSerializer.toJson(TextComponent.fromLegacy(entry)); + } + return Component.Serializer.fromJson(json, RegistryAccess.EMPTY); }) .toArray(Component[]::new); diff --git a/src/main/resources/motd sets/example.txt b/src/main/resources/motd sets/example.txt index 0970723..d4486bf 100644 --- a/src/main/resources/motd sets/example.txt +++ b/src/main/resources/motd sets/example.txt @@ -7,3 +7,5 @@ Random MOTD for every ping Or just one line. If it doesn't fit it will be passed onto the second line. Put your own files in this directory + +["",{"text":"Also supports","color":"#A18D94"},{"text":" JSON","color":"#FF00FF"},{"text":"\n"},{"text":"Java","color":"dark_aqua"},{"text":"Script ","color":"aqua"},{"text":"Object","color":"gray"},{"text":" Notation","color":"red"}] \ No newline at end of file From d03f8e35fb993b90a5d5135a4e121bad54b3edc5 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 14:52:36 +0100 Subject: [PATCH 25/89] Move cache where it should be --- src/main/java/eu/m724/tweaks/updater/UpdaterManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java index 9bb1904..f62bd19 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -28,7 +28,7 @@ public class UpdaterManager { public UpdaterManager(Plugin plugin) { this.plugin = plugin; - cacheFile = new File(plugin.getDataFolder(), "storage/updater"); + cacheFile = new File(plugin.getDataFolder(), "storage/cache/updater"); } public void init(PluginCommand updatesCommand){ From c8d394c31e86d5b1899d09b0355f320ad32f6ffd Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 15:37:05 +0100 Subject: [PATCH 26/89] Add killswitch feature --- KILLSWITCH.md | 32 +++++ .../java/eu/m724/tweaks/TweaksConfig.java | 13 +- .../java/eu/m724/tweaks/TweaksPlugin.java | 8 +- .../tweaks/killswitch/KillswitchManager.java | 125 ++++++++++++++++++ .../eu/m724/tweaks/killswitch/Ratelimit.java | 26 ++++ src/main/resources/config.yml | 10 ++ src/main/resources/plugin.yml | 6 +- 7 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 KILLSWITCH.md create mode 100644 src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java create mode 100644 src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java diff --git a/KILLSWITCH.md b/KILLSWITCH.md new file mode 100644 index 0000000..4ac09e3 --- /dev/null +++ b/KILLSWITCH.md @@ -0,0 +1,32 @@ +Killswitch immediately stops the server. + +### Warning +This terminates the server process, meaning it's like you'd pull the power. \ +So you will lose some progress (since the last auto save), or worst case your world (or other data) gets corrupted. + +Terminal froze after kill? `reset` + +### Over a command +No key is required. \ +`/servkill` is the command. Permission: `tweaks724.servkill`. \ +You must grant the permission manually, like with a permission plugin - it's not automatically assigned even to OPs. + +### Over HTTP +HTTP is insecure, meaning others *could* intercept your request to the server and get your key. \ +To encrypt, put this behind a proxy to get HTTPS or a VPN (directly to the server, not a commercial VPN) \ +Or regenerate the key after every usage. + +Make a GET request to `/key/` + +Example: +``` +https://127.0.0.1:57932/key/lNwANMSZhLiTWhNxSoqQ5Q== +|_ server address _| |_ base64 encoded key _| +``` + +The response is a 404 no matter what. Either way, you will notice that the server has stopped. + +The key is generated to `plugins/Tweaks724/storage/killswitch key` \ +To use it with HTTP server, encode it to base64. + +Rate limit is 1 request / 5 minutes \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 3a10a27..9c54a02 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -57,7 +57,10 @@ public record TweaksConfig( boolean redstoneEnabled, String redstoneListen, - Map knockbackModifiers + Map knockbackModifiers, + + boolean killswitchEnabled, + String killswitchListen ) { public static final int CONFIG_VERSION = 2; private static TweaksConfig config; @@ -129,6 +132,9 @@ public record TweaksConfig( // this is processed when initing Map knockbackModifiers = config.getConfigurationSection("knockback").getValues(false); + boolean killswitchEnabled = config.getBoolean("killswitch.enabled"); + String killswitchListen = config.getString("killswitch.listen"); + TweaksConfig.config = new TweaksConfig( debug, metrics, locale, worldborderExpand, worldborderHide, @@ -143,7 +149,8 @@ public record TweaksConfig( sleepEnabled, sleepInstant, authEnabled, authForce, authHostname, redstoneEnabled, redstoneListen, - knockbackModifiers + knockbackModifiers, + killswitchEnabled, killswitchListen ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 7c5e238..575b935 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -14,6 +14,7 @@ import eu.m724.tweaks.door.DoorKnockListener; import eu.m724.tweaks.door.DoorOpenListener; import eu.m724.tweaks.full.FullListener; import eu.m724.tweaks.hardcore.HardcoreManager; +import eu.m724.tweaks.killswitch.KillswitchManager; import eu.m724.tweaks.knockback.KnockbackListener; import eu.m724.tweaks.motd.MotdManager; import eu.m724.tweaks.ping.F3NameListener; @@ -129,6 +130,11 @@ public class TweaksPlugin extends MStatsPlugin { DebugLogger.fine("Enabling Knockback"); new KnockbackListener(this); + if (config.killswitchEnabled()) { + DebugLogger.fine("Enabling Killswitch"); + new KillswitchManager(this).init(getCommand("servkill")); + } + /* end modules */ if (config.metrics()) { diff --git a/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java b/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java new file mode 100644 index 0000000..c16f75d --- /dev/null +++ b/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java @@ -0,0 +1,125 @@ +/* + * 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.killswitch; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.TweaksPlugin; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +public class KillswitchManager implements CommandExecutor, HttpHandler { + private final Plugin plugin; + private final Ratelimit ratelimit = new Ratelimit(); + + private byte[] secret; + private String secretEncoded; + + public KillswitchManager(Plugin plugin) { + this.plugin = plugin; + } + + private void loadKey(File file) { + if (file.exists()) { + try { + this.secret = Files.readAllBytes(file.toPath()); + } catch (IOException e) { + throw new RuntimeException("Reading killswitch key", e); + } + DebugLogger.fine("Loaded key"); + } else { + byte[] buf = new byte[16]; + + try { + SecureRandom.getInstanceStrong().nextBytes(buf); + Files.write(file.toPath(), buf); + } catch (IOException | NoSuchAlgorithmException e) { + throw new RuntimeException("Generating killswitch key", e); + } + + this.secret = buf; + DebugLogger.info("Killswitch key generated and saved to " + file.getPath()); + } + + this.secretEncoded = Base64.getEncoder().encodeToString(secret); + } + + public void init(PluginCommand serverKillCommand) { + serverKillCommand.setExecutor(this); + + if (TweaksConfig.getConfig().killswitchListen() != null) { + loadKey(new File(plugin.getDataFolder(), "storage/killswitch key")); + + ratelimit.runTaskTimerAsynchronously(plugin, 0, 20 * 300); + + var listenAddress = TweaksConfig.getConfig().killswitchListen().split(":"); + InetSocketAddress bindAddress; + if (listenAddress.length == 1) { + bindAddress = new InetSocketAddress(Integer.parseInt(listenAddress[0])); + } else { + bindAddress = new InetSocketAddress(listenAddress[0], Integer.parseInt(listenAddress[1])); + } + + try { + HttpServer server = HttpServer.create(bindAddress, 0); + server.createContext("/", this); + server.setExecutor(null); + server.start(); + DebugLogger.fine("server started"); + } catch (IOException e) { + throw new RuntimeException("Starting HTTP server", e); + } + } + } + + private void kill() { + Runtime.getRuntime().halt(0); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + kill(); + return true; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + exchange.sendResponseHeaders(404, -1); + + var path = exchange.getRequestURI().getPath(); + if (!path.startsWith("/key/")) return; + + var address = exchange.getRemoteAddress().getAddress(); + if (!ratelimit.submitRequest(address)) { + DebugLogger.fine(address + " is ratelimited"); + return; + } + + var key = path.substring(5); + if (key.equals(secretEncoded)) { + DebugLogger.fine("Got a request with valid key"); + kill(); + } else { + DebugLogger.fine("Got a request with invalid key"); + } + } +} diff --git a/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java b/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java new file mode 100644 index 0000000..40039b6 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java @@ -0,0 +1,26 @@ +/* + * 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.killswitch; + +import org.bukkit.scheduler.BukkitRunnable; + +import java.net.InetAddress; +import java.util.HashSet; +import java.util.Set; + +public class Ratelimit extends BukkitRunnable { + private Set requests = new HashSet<>(); + + boolean submitRequest(InetAddress address) { + return requests.add(address); + } + + @Override + public void run() { + requests = new HashSet<>(); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bcf91fa..9c49759 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -104,6 +104,7 @@ auth: domain: "replace.me" # Adds gateways emitting redstone, controlled over internet +# https://git.m724.eu/Minecon724/tweaks724/src/branch/master/RETSTONE.md retstone: enabled: true # This takes host:port, listens on UDP @@ -117,6 +118,15 @@ knockback: tnt: 5 creeper: 0.7 +# Kills server after /servkill or HTTP request +# https://git.m724.eu/Minecon724/tweaks724/src/branch/master/KILLSWITCH.md +killswitch: + enabled: true + # This takes host:port, starts an HTTP server + # To disable HTTP server, set to null + listen: 127.0.0.1:57932 + + # Finally, thank you for downloading Tweaks724, I hope you enjoy! # Don't modify unless told to diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e96250e..fac4b46 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -37,6 +37,9 @@ commands: retstone: description: Retstone commands permission: tweaks724.retstone + servkill: + description: Immediately stop the server + permission: tweaks724.servkill permissions: tweaks724: @@ -54,4 +57,5 @@ permissions: default: op retstone: default: op - + servkill: + default: false From ec59b3d293d85fbc53e8be4d04984978bdebc6d6 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 15:37:43 +0100 Subject: [PATCH 27/89] Create a directory for docs since it's getting crowded --- DEVELOPMENT.md => docs/DEVELOPMENT.md | 0 KILLSWITCH.md => docs/KILLSWITCH.md | 0 RETSTONE.md => docs/RETSTONE.md | 0 retstone.py => docs/retstone.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename DEVELOPMENT.md => docs/DEVELOPMENT.md (100%) rename KILLSWITCH.md => docs/KILLSWITCH.md (100%) rename RETSTONE.md => docs/RETSTONE.md (100%) rename retstone.py => docs/retstone.py (100%) diff --git a/DEVELOPMENT.md b/docs/DEVELOPMENT.md similarity index 100% rename from DEVELOPMENT.md rename to docs/DEVELOPMENT.md diff --git a/KILLSWITCH.md b/docs/KILLSWITCH.md similarity index 100% rename from KILLSWITCH.md rename to docs/KILLSWITCH.md diff --git a/RETSTONE.md b/docs/RETSTONE.md similarity index 100% rename from RETSTONE.md rename to docs/RETSTONE.md diff --git a/retstone.py b/docs/retstone.py similarity index 100% rename from retstone.py rename to docs/retstone.py From c5743dbb64ec2e035f6848a0c7a622c56efa449c Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 16:20:28 +0100 Subject: [PATCH 28/89] Fix missing library on Paper --- src/main/java/eu/m724/tweaks/DebugLogger.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java index 45b7ba5..2b91bee 100644 --- a/src/main/java/eu/m724/tweaks/DebugLogger.java +++ b/src/main/java/eu/m724/tweaks/DebugLogger.java @@ -1,13 +1,11 @@ /* - * Copyright (C) 2024 Minecon724 + * 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; -import org.fusesource.jansi.Ansi; - import java.util.logging.Level; import java.util.logging.Logger; @@ -43,7 +41,7 @@ public class DebugLogger { if (level.intValue() < Level.INFO.intValue()) { // levels below info are never logged even if set for some reason level = Level.INFO; // colors text gray (cyan is close to gray) - message = Ansi.ansi().fg(Ansi.Color.CYAN).a(message).reset().toString(); + message = "\033[36m" + message + "\033[39m"; } logger.log(level, message); From ef85f8f4b3f94be0ae87c1227ecb4e5e691eaac2 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 16:22:42 +0100 Subject: [PATCH 29/89] [maven-release-plugin] prepare release tweaks-0.1.11 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4427771..d4c5e48 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.11-SNAPSHOT + 0.1.11 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.11 \ No newline at end of file From 32bacc96e87e0aa7d0e6af900605af1fb4cff860 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 16:22:44 +0100 Subject: [PATCH 30/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d4c5e48..77413b0 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.11 + 0.1.12-SNAPSHOT 21 @@ -213,6 +213,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.11 + HEAD \ No newline at end of file From 0d87ca8f76b298f62aa8b66057e75e4ecb8c591a Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 1 Jan 2025 16:32:28 +0100 Subject: [PATCH 31/89] Add to README --- README.md | 7 ++++++- docs/README.md | 3 +++ pom.xml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index 1e49879..8b6db43 100644 --- a/README.md +++ b/README.md @@ -83,11 +83,16 @@ Issue messages that the player needs to read to keep playing, and that make an a ### Remote redstone Adds a "gateway" item that are controlled over internet. \ -[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/RETSTONE.md) +[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/docs/RETSTONE.md) ### Knockback Control knockback dealt by entities +### Kill switch +Quickly kills (terminates) the server on trigger, via command or HTTP request. +[KILLSWITCH.md for more info](/Minecon724/tweaks724/src/branch/master/docs/KILLSWITCH.md) + + ### Utility commands - `/ping` - displays player ping \ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c44787d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +Here's the documentation. + +Click above on a file to read more about a topic. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 77413b0..71e68e2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ From 6ad6550f5d0cfe034cff5ba6e618cc96f8f7bfa8 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 12:54:08 +0100 Subject: [PATCH 32/89] Fix logging in updater --- .../eu/m724/tweaks/updater/UpdateChecker.java | 19 ++++++++++--------- .../m724/tweaks/updater/UpdaterManager.java | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java index 2687e32..03dfd1f 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -19,26 +19,28 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletionException; +import java.util.logging.Logger; import java.util.stream.Collectors; public class UpdateChecker extends BukkitRunnable { + private final Logger logger; private final Set resources; static final Set availableUpdates = new HashSet<>(); static LocalTime lastChecked = null; - UpdateChecker(Set resources) { + UpdateChecker(Logger logger, Set resources) { + this.logger = logger; this.resources = resources; // TODO make a copy? } private void checkAll() { - //logger.info("Checking for updates"); + DebugLogger.fine("Checking for updates"); lastChecked = LocalTime.now(ZoneOffset.UTC); availableUpdates.clear(); for (VersionedResource versionedResource : Set.copyOf(resources)) { String pluginName = versionedResource.resource().plugin().getName(); - //logger.info(versionedResource.resource().resourceId() + " " + versionedResource.resource().plugin().getName()); int page = versionedResource.running() != null ? versionedResource.running().page() : 1; try { @@ -46,14 +48,13 @@ public class UpdateChecker extends BukkitRunnable { if (!versionedResource.equals(newResource)) { resources.remove(versionedResource); if (newResource.running() == null) { - DebugLogger.info("Unable to find installed version of %s".formatted(pluginName)); + logger.warning("Unable to find installed version of %s".formatted(pluginName)); if (versionedResource.running() != null) { - DebugLogger.info("Did you downgrade %s? If so, clear cache".formatted(pluginName)); + logger.warning("Did you downgrade %s? If so, clear cache".formatted(pluginName)); } } else { if (!newResource.running().equals(newResource.latest())) { availableUpdates.add(newResource); - //logger.info("Update available for %s. %d -> %d".formatted(pluginName, newResource.running().updateId(), newResource.latest().updateId())); } } resources.add(newResource); @@ -67,11 +68,11 @@ public class UpdateChecker extends BukkitRunnable { private void alert() { int n = availableUpdates.size(); if (n == 0) return; - DebugLogger.info(Language.getString("updateAvailableNotice", n)); + logger.info(Language.getString("updateAvailableNotice", n)); availableUpdates.stream() .map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label())) - .forEach(DebugLogger::info); + .forEach(logger::info); } @Override diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java index f62bd19..b540a23 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java @@ -60,7 +60,7 @@ public class UpdaterManager { )).collect(Collectors.toSet()); - new UpdateChecker(versionedResources) + new UpdateChecker(plugin.getLogger(), versionedResources) .runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20); updatesCommand.setExecutor(new UpdaterCommands()); From 81fa6440a0bde25812ea55a971875e1371dbf70c Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 13:19:23 +0100 Subject: [PATCH 33/89] Improve hardcore RNG --- .../java/eu/m724/tweaks/TweaksConfig.java | 4 +-- .../m724/tweaks/hardcore/HardcoreManager.java | 35 ++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 9c54a02..7a791cc 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -45,7 +45,7 @@ public record TweaksConfig( boolean updaterEnabled, boolean hardcoreEnabled, - float hardcoreChance, + double hardcoreChance, boolean sleepEnabled, boolean sleepInstant, @@ -117,7 +117,7 @@ public record TweaksConfig( boolean updaterEnabled = config.getBoolean("updater.enabled"); boolean hardcoreEnabled = config.getBoolean("hardcore.enabled"); - float hardcoreChance = (float) config.getDouble("hardcore.chance"); + double hardcoreChance = config.getDouble("hardcore.chance"); boolean sleepEnabled = config.getBoolean("sleep.enabled"); boolean sleepInstant = config.getBoolean("sleep.instant"); diff --git a/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java b/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java index 0dc632b..e03179e 100644 --- a/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java +++ b/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -8,14 +8,40 @@ package eu.m724.tweaks.hardcore; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.*; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; +import net.minecraft.world.level.levelgen.RandomSupport; +import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus; import org.bukkit.plugin.Plugin; +import java.math.BigDecimal; +import java.math.BigInteger; + +// how we do it is much faster than any Random public class HardcoreManager { - private final float chance = TweaksConfig.getConfig().hardcoreChance(); + private final double chance = TweaksConfig.getConfig().hardcoreChance(); + + private final long chanceLong = BigInteger.valueOf(Long.MIN_VALUE) + .add( + new BigDecimal( + BigInteger.valueOf(Long.MAX_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE)) + ).multiply( + BigDecimal.valueOf(chance) + ).toBigInteger() + ).longValue(); + + private final Xoroshiro128PlusPlus rng = new Xoroshiro128PlusPlus( + RandomSupport.generateUniqueSeed(), + RandomSupport.generateUniqueSeed() + ); public void init(Plugin plugin) { + DebugLogger.fine("Chance long: " + chanceLong); + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( plugin, ListenerPriority.NORMAL, @@ -24,9 +50,8 @@ public class HardcoreManager { @Override public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); - int entityId = packet.getIntegers().read(0); - if (chance > ((48271 * entityId) % 65537) / 65537f) // gotta be fast + if (rng.nextLong() < chanceLong) // the "is hardcore" boolean https://wiki.vg/Protocol#Login_.28play.29 packet.getBooleans().write(0, true); } From fa96487ef65ecb16c9cc5a79c081b2889d27488d Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 18:56:42 +0100 Subject: [PATCH 34/89] Add swing module --- README.md | 3 + .../java/eu/m724/tweaks/TweaksConfig.java | 13 ++- .../java/eu/m724/tweaks/TweaksPlugin.java | 6 ++ .../eu/m724/tweaks/swing/SwingManager.java | 89 +++++++++++++++++++ src/main/resources/config.yml | 9 ++ 5 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/swing/SwingManager.java diff --git a/README.md b/README.md index 8b6db43..7d830ff 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,9 @@ Control knockback dealt by entities Quickly kills (terminates) the server on trigger, via command or HTTP request. [KILLSWITCH.md for more info](/Minecon724/tweaks724/src/branch/master/docs/KILLSWITCH.md) +### Swing through grass + + ### Utility commands diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 7a791cc..011e74e 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -60,7 +60,11 @@ public record TweaksConfig( Map knockbackModifiers, boolean killswitchEnabled, - String killswitchListen + String killswitchListen, + + boolean swingEnabled, + boolean swingSword, + int swingMode ) { public static final int CONFIG_VERSION = 2; private static TweaksConfig config; @@ -135,6 +139,10 @@ public record TweaksConfig( boolean killswitchEnabled = config.getBoolean("killswitch.enabled"); String killswitchListen = config.getString("killswitch.listen"); + boolean swingEnabled = config.getBoolean("swing.enabled"); + boolean swingSword = config.getBoolean("swing.sword"); + int swingMode = config.getInt("swing.mode"); + TweaksConfig.config = new TweaksConfig( debug, metrics, locale, worldborderExpand, worldborderHide, @@ -150,7 +158,8 @@ public record TweaksConfig( authEnabled, authForce, authHostname, redstoneEnabled, redstoneListen, knockbackModifiers, - killswitchEnabled, killswitchListen + killswitchEnabled, killswitchListen, + swingEnabled, swingSword, swingMode ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 575b935..b0abd9a 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -22,6 +22,7 @@ import eu.m724.tweaks.ping.PingChecker; import eu.m724.tweaks.pomodoro.PomodoroManager; import eu.m724.tweaks.redstone.RedstoneManager; import eu.m724.tweaks.sleep.SleepManager; +import eu.m724.tweaks.swing.SwingManager; import eu.m724.tweaks.updater.UpdaterManager; import eu.m724.tweaks.worldborder.WorldBorderExpander; import eu.m724.tweaks.worldborder.WorldBorderHider; @@ -135,6 +136,11 @@ public class TweaksPlugin extends MStatsPlugin { new KillswitchManager(this).init(getCommand("servkill")); } + if (config.swingEnabled()) { + DebugLogger.fine("Enabling Swing"); + new SwingManager(this).init(); + } + /* end modules */ if (config.metrics()) { diff --git a/src/main/java/eu/m724/tweaks/swing/SwingManager.java b/src/main/java/eu/m724/tweaks/swing/SwingManager.java new file mode 100644 index 0000000..6acfd75 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/swing/SwingManager.java @@ -0,0 +1,89 @@ +/* + * 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.swing; + +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksConfig; +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.plugin.Plugin; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class SwingManager implements Listener { + private final Plugin plugin; + + private final int mode; + private final boolean useTools; + private Set tools = new HashSet<>(); + + public SwingManager(Plugin plugin) { + this.plugin = plugin; + + this.mode = TweaksConfig.getConfig().swingMode(); + + if (mode != 0 && mode != 1) + throw new IllegalArgumentException("Mode " + mode + " is invalid. It must be 0 or 1."); + + if (TweaksConfig.getConfig().swingSword()) { + Arrays.stream(Material.values()) + .filter(m -> m.name().contains("SWORD")) + .forEach(m -> tools.add(m)); + } + + this.useTools = !tools.isEmpty(); + DebugLogger.fine("Tools: " + tools.size()); + } + + public void init() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onBreak(BlockBreakEvent event) { + var type = event.getBlock().getType(); + if (type.isOccluding()) return; + + var player = event.getPlayer(); + + if (useTools) { + var tool = player.getInventory().getItemInMainHand().getType(); + if (!tools.contains(tool)) return; + } + + Entity entity = null; + + if (mode == 0) { + entity = event.getBlock().getWorld() + .getNearbyEntities(event.getBlock().getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5) + .stream().filter(e -> (e instanceof LivingEntity && e != player)) + .findFirst().orElse(null); + } else if (mode == 1) { + var result = player.getWorld().rayTraceEntities( + player.getEyeLocation(), + player.getEyeLocation().getDirection(), + player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE).getValue(), + e -> e != player + ); + + if (result != null) + entity = result.getHitEntity(); + } + + if (entity != null) { + player.attack(entity); + DebugLogger.fine("Swing " + player.getName() + " hit " + entity.getName()); + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 9c49759..4524099 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -126,6 +126,15 @@ killswitch: # To disable HTTP server, set to null listen: 127.0.0.1:57932 +# Swing through grass (and alike) +swing: + enabled: true + # Only sword + sword: false + # 0 - entity inside broken block / can't attack entity behind the block + # 1 - raycasted from player / can attack entity behind the block (within normal reach) + mode: 0 + # Finally, thank you for downloading Tweaks724, I hope you enjoy! From 4bf6ec5ae7b12e7131c765f372effdc671d8910d Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 19:44:24 +0100 Subject: [PATCH 35/89] Always use 1.21.1 API --- pom.xml | 2 +- src/main/java/eu/m724/tweaks/swing/SwingManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 71e68e2..45ceefd 100644 --- a/pom.xml +++ b/pom.xml @@ -167,7 +167,7 @@ org.spigotmc spigot-api - ${project.spigot.version} + 1.21.1-R0.1-SNAPSHOT provided diff --git a/src/main/java/eu/m724/tweaks/swing/SwingManager.java b/src/main/java/eu/m724/tweaks/swing/SwingManager.java index 6acfd75..b7ccb5f 100644 --- a/src/main/java/eu/m724/tweaks/swing/SwingManager.java +++ b/src/main/java/eu/m724/tweaks/swing/SwingManager.java @@ -73,7 +73,7 @@ public class SwingManager implements Listener { var result = player.getWorld().rayTraceEntities( player.getEyeLocation(), player.getEyeLocation().getDirection(), - player.getAttribute(Attribute.ENTITY_INTERACTION_RANGE).getValue(), + player.getAttribute(Attribute.PLAYER_ENTITY_INTERACTION_RANGE).getValue(), e -> e != player ); From afed2a8f780a73b2962c84c377d46cfe97212e7b Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 20:21:12 +0100 Subject: [PATCH 36/89] Add sleep heal option --- .../java/eu/m724/tweaks/TweaksConfig.java | 4 +++- .../eu/m724/tweaks/sleep/SleepListener.java | 22 +++++++++++-------- src/main/resources/config.yml | 8 ++++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 011e74e..4a34ec7 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -49,6 +49,7 @@ public record TweaksConfig( boolean sleepEnabled, boolean sleepInstant, + double sleepHeal, boolean authEnabled, boolean authForce, @@ -125,6 +126,7 @@ public record TweaksConfig( boolean sleepEnabled = config.getBoolean("sleep.enabled"); boolean sleepInstant = config.getBoolean("sleep.instant"); + double sleepHeal = config.getDouble("sleep.heal"); boolean authEnabled = config.getBoolean("auth.enabled"); boolean authForce = config.getBoolean("auth.force"); @@ -154,7 +156,7 @@ public record TweaksConfig( pomodoroEnabled, pomodoroForce, updaterEnabled, hardcoreEnabled, hardcoreChance, - sleepEnabled, sleepInstant, + sleepEnabled, sleepInstant, sleepHeal, authEnabled, authForce, authHostname, redstoneEnabled, redstoneListen, knockbackModifiers, diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java index 6e0c23c..ad3736e 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java +++ b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -21,6 +21,7 @@ import java.util.Set; public class SleepListener implements Listener { private final boolean instant = TweaksConfig.getConfig().sleepInstant(); + private final double heal = TweaksConfig.getConfig().sleepHeal() * 2; // hearts to half hearts private final Set skippedCurrentNight = new HashSet<>(); private long lastDay = 0; @@ -30,14 +31,16 @@ public class SleepListener implements Listener { if (event.getBedEnterResult() == PlayerBedEnterEvent.BedEnterResult.OK) { SleepState.playersSleeping++; - if (instant) { - World world = event.getPlayer().getWorld(); + World world = event.getPlayer().getWorld(); - long day = world.getFullTime() / 24000; - if (day != lastDay) skippedCurrentNight.clear(); - lastDay = day; + long day = world.getFullTime() / 24000; + if (day != lastDay) skippedCurrentNight.clear(); + lastDay = day; - if (!skippedCurrentNight.contains(event.getPlayer())) { + if (!skippedCurrentNight.contains(event.getPlayer())) { + event.getPlayer().setHealth(event.getPlayer().getHealth() + heal); + + if (instant) { double onePlayerRatio = 1 / (event.getPlayer().getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0)); world.setTime(Math.min(world.getTime() + (long) (10917 * onePlayerRatio), 23459)); skippedCurrentNight.add(event.getPlayer()); @@ -53,8 +56,9 @@ public class SleepListener implements Listener { } @EventHandler - public void onPlayerBedLeave(TimeSkipEvent event) { - if (event.getSkipReason() == TimeSkipEvent.SkipReason.NIGHT_SKIP) + public void onTimeSkip(TimeSkipEvent event) { + if (event.getSkipReason() == TimeSkipEvent.SkipReason.NIGHT_SKIP) { event.setCancelled(true); + } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4524099..4aa2426 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -83,6 +83,9 @@ hardcore: # Makes sleeping # And adds a nice animation +# Percentage: playersSleepingPercentage gamerule +# If instant: how much % of players to skip the night +# If not: how much % make skipping full speed sleep: enabled: true # This gives every player a "share" of the night @@ -90,9 +93,8 @@ sleep: # For example, if 5 players online and night is 5 minutes, one can go to sleep and skip 1 minute of the night # Leaving the bed and reentering it does nothing instant: false - # Percentage: playersSleepingPercentage gamerule - # If instant: how much % of players to skip the night - # If not: how much % make skipping full speed + # How many hearts to heal after sleeping + heal: 2.0 # "Hostname" authentication # This makes a player need to join a unique hostname like "asd123.example.com" where "asd123" is the key From 6e45491508ff105f952586eb1cdef9cb37fd35c4 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 20:23:18 +0100 Subject: [PATCH 37/89] Don't touch vertical knockback --- .../java/eu/m724/tweaks/knockback/KnockbackListener.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java index 14e4764..3239d5c 100644 --- a/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java +++ b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -13,12 +13,13 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityKnockbackByEntityEvent; import org.bukkit.plugin.Plugin; +import org.bukkit.util.Vector; import java.util.HashMap; import java.util.Map; public class KnockbackListener implements Listener { - private final Map modifiers = new HashMap<>(); + private final Map modifiers = new HashMap<>(); public KnockbackListener(Plugin plugin) { TweaksConfig.getConfig().knockbackModifiers().forEach((k, v) -> { @@ -45,7 +46,7 @@ public class KnockbackListener implements Listener { } if (mod == 1) return; - modifiers.put(type, mod); + modifiers.put(type, new Vector(mod, mod >= 1 ? mod : 1, mod)); // don't touch vertical }); if (!modifiers.isEmpty()) From 724a36c8031e60ba20186e0d9422e59142dfc678 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 20:29:15 +0100 Subject: [PATCH 38/89] Add heal to README --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7d830ff..5522659 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,11 @@ Hardcore hearts by chance ### Sleep Sleeping doesn't skip night, but speeds it up. The more players, the faster it goes. - Instant sleep \ -One can instantly skip, but only a part of the night. \ -There's 5 players on the server. A night is 10 minutes long. \ -Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping + One can instantly skip, but only a part of the night. \ + There's 5 players on the server. A night is 10 minutes long. \ + Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping +- Heal \ + Sleeping heals ### Authentication Players are given a unique subdomain like "\.example.com" and they must use it to join \ From e59b95e2ef4e11dae173ed8c96546a760faf1d3f Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 2 Jan 2025 20:29:59 +0100 Subject: [PATCH 39/89] Auto swing mode --- .../java/eu/m724/tweaks/TweaksConfig.java | 8 +--- .../eu/m724/tweaks/sleep/SleepListener.java | 4 +- .../eu/m724/tweaks/swing/SwingManager.java | 38 ++++++------------- src/main/resources/config.yml | 7 +--- 4 files changed, 17 insertions(+), 40 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 4a34ec7..4196fab 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -63,9 +63,7 @@ public record TweaksConfig( boolean killswitchEnabled, String killswitchListen, - boolean swingEnabled, - boolean swingSword, - int swingMode + boolean swingEnabled ) { public static final int CONFIG_VERSION = 2; private static TweaksConfig config; @@ -142,8 +140,6 @@ public record TweaksConfig( String killswitchListen = config.getString("killswitch.listen"); boolean swingEnabled = config.getBoolean("swing.enabled"); - boolean swingSword = config.getBoolean("swing.sword"); - int swingMode = config.getInt("swing.mode"); TweaksConfig.config = new TweaksConfig( debug, metrics, locale, @@ -161,7 +157,7 @@ public record TweaksConfig( redstoneEnabled, redstoneListen, knockbackModifiers, killswitchEnabled, killswitchListen, - swingEnabled, swingSword, swingMode + swingEnabled ); return TweaksConfig.config; diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java index ad3736e..8aa5579 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java +++ b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java @@ -38,13 +38,13 @@ public class SleepListener implements Listener { lastDay = day; if (!skippedCurrentNight.contains(event.getPlayer())) { - event.getPlayer().setHealth(event.getPlayer().getHealth() + heal); - if (instant) { double onePlayerRatio = 1 / (event.getPlayer().getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0)); world.setTime(Math.min(world.getTime() + (long) (10917 * onePlayerRatio), 23459)); skippedCurrentNight.add(event.getPlayer()); } + + event.getPlayer().setHealth(event.getPlayer().getHealth() + heal); } } diff --git a/src/main/java/eu/m724/tweaks/swing/SwingManager.java b/src/main/java/eu/m724/tweaks/swing/SwingManager.java index b7ccb5f..b3cd2cb 100644 --- a/src/main/java/eu/m724/tweaks/swing/SwingManager.java +++ b/src/main/java/eu/m724/tweaks/swing/SwingManager.java @@ -7,7 +7,6 @@ package eu.m724.tweaks.swing; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; import org.bukkit.Material; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Entity; @@ -24,25 +23,15 @@ import java.util.Set; public class SwingManager implements Listener { private final Plugin plugin; - private final int mode; - private final boolean useTools; - private Set tools = new HashSet<>(); + private final Set tools = new HashSet<>(); public SwingManager(Plugin plugin) { this.plugin = plugin; - this.mode = TweaksConfig.getConfig().swingMode(); + Arrays.stream(Material.values()) + .filter(m -> m.name().contains("SWORD")) + .forEach(tools::add); - if (mode != 0 && mode != 1) - throw new IllegalArgumentException("Mode " + mode + " is invalid. It must be 0 or 1."); - - if (TweaksConfig.getConfig().swingSword()) { - Arrays.stream(Material.values()) - .filter(m -> m.name().contains("SWORD")) - .forEach(m -> tools.add(m)); - } - - this.useTools = !tools.isEmpty(); DebugLogger.fine("Tools: " + tools.size()); } @@ -56,20 +45,10 @@ public class SwingManager implements Listener { if (type.isOccluding()) return; var player = event.getPlayer(); - - if (useTools) { - var tool = player.getInventory().getItemInMainHand().getType(); - if (!tools.contains(tool)) return; - } - + var tool = player.getInventory().getItemInMainHand().getType(); Entity entity = null; - if (mode == 0) { - entity = event.getBlock().getWorld() - .getNearbyEntities(event.getBlock().getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5) - .stream().filter(e -> (e instanceof LivingEntity && e != player)) - .findFirst().orElse(null); - } else if (mode == 1) { + if (tools.contains(tool)) { // if sword, raycast to hit farther var result = player.getWorld().rayTraceEntities( player.getEyeLocation(), player.getEyeLocation().getDirection(), @@ -79,6 +58,11 @@ public class SwingManager implements Listener { if (result != null) entity = result.getHitEntity(); + } else { + entity = event.getBlock().getWorld() + .getNearbyEntities(event.getBlock().getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5) + .stream().filter(e -> (e instanceof LivingEntity && e != player)) + .findFirst().orElse(null); } if (entity != null) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4aa2426..dd439da 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -129,13 +129,10 @@ killswitch: listen: 127.0.0.1:57932 # Swing through grass (and alike) +# If using sword, you can also hit behind the grass +# If not, you can only hit the entity in the grass swing: enabled: true - # Only sword - sword: false - # 0 - entity inside broken block / can't attack entity behind the block - # 1 - raycasted from player / can attack entity behind the block (within normal reach) - mode: 0 # Finally, thank you for downloading Tweaks724, I hope you enjoy! From 648535fd222d928f0b43feee5b8438a5a92bd8fc Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 3 Jan 2025 13:14:21 +0100 Subject: [PATCH 40/89] Make abstract Before it's too late --- pom.xml | 4 +- src/main/java/eu/m724/tweaks/DebugLogger.java | 38 ++++--- .../java/eu/m724/tweaks/TweaksModule.java | 87 +++++++++++++++ .../java/eu/m724/tweaks/TweaksPlugin.java | 100 ++++++++---------- .../eu/m724/tweaks/alert/AlertCommand.java | 10 +- .../eu/m724/tweaks/alert/AlertManager.java | 90 ---------------- .../eu/m724/tweaks/alert/AlertModule.java | 74 +++++++++++++ .../java/eu/m724/tweaks/auth/AuthManager.java | 25 ----- .../java/eu/m724/tweaks/auth/AuthModule.java | 19 ++++ .../eu/m724/tweaks/chat/ChatCommands.java | 10 +- .../eu/m724/tweaks/chat/ChatListener.java | 19 ++-- .../{ChatManager.java => ChatModule.java} | 29 ++--- .../m724/tweaks/compass/CompassManager.java | 21 ---- ...ompassListener.java => CompassModule.java} | 15 ++- ...nockListener.java => DoorKnockModule.java} | 10 +- ...rOpenListener.java => DoorOpenModule.java} | 10 +- .../{FullListener.java => FullModule.java} | 10 +- .../m724/tweaks/hardcore/HardcoreManager.java | 60 ----------- .../m724/tweaks/hardcore/HardcoreModule.java | 52 +++++++++ ...itchManager.java => KillswitchModule.java} | 25 ++--- ...backListener.java => KnockbackModule.java} | 12 +-- .../{MotdManager.java => MotdModule.java} | 76 +++++-------- .../java/eu/m724/tweaks/ping/PingChecker.java | 4 +- .../m724/tweaks/pomodoro/PomodoroManager.java | 25 ----- .../m724/tweaks/pomodoro/PomodoroModule.java | 19 ++++ ...dstoneManager.java => RedstoneModule.java} | 34 +++--- .../eu/m724/tweaks/sleep/SleepManager.java | 18 ---- .../eu/m724/tweaks/sleep/SleepModule.java | 19 ++++ .../{SwingManager.java => SwingModule.java} | 17 ++- .../eu/m724/tweaks/updater/UpdateChecker.java | 9 +- ...UpdaterManager.java => UpdaterModule.java} | 30 ++---- ...nder.java => WorldBorderExpandModule.java} | 13 +-- .../worldborder/WorldBorderHideModule.java | 51 +++++++++ .../tweaks/worldborder/WorldBorderHider.java | 74 ------------- 34 files changed, 549 insertions(+), 560 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/TweaksModule.java delete mode 100644 src/main/java/eu/m724/tweaks/alert/AlertManager.java create mode 100644 src/main/java/eu/m724/tweaks/alert/AlertModule.java delete mode 100644 src/main/java/eu/m724/tweaks/auth/AuthManager.java create mode 100644 src/main/java/eu/m724/tweaks/auth/AuthModule.java rename src/main/java/eu/m724/tweaks/chat/{ChatManager.java => ChatModule.java} (87%) delete mode 100644 src/main/java/eu/m724/tweaks/compass/CompassManager.java rename src/main/java/eu/m724/tweaks/compass/{CompassListener.java => CompassModule.java} (92%) rename src/main/java/eu/m724/tweaks/door/{DoorKnockListener.java => DoorKnockModule.java} (90%) rename src/main/java/eu/m724/tweaks/door/{DoorOpenListener.java => DoorOpenModule.java} (92%) rename src/main/java/eu/m724/tweaks/full/{FullListener.java => FullModule.java} (71%) delete mode 100644 src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java create mode 100644 src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java rename src/main/java/eu/m724/tweaks/killswitch/{KillswitchManager.java => KillswitchModule.java} (82%) rename src/main/java/eu/m724/tweaks/knockback/{KnockbackListener.java => KnockbackModule.java} (85%) rename src/main/java/eu/m724/tweaks/motd/{MotdManager.java => MotdModule.java} (54%) delete mode 100644 src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java create mode 100644 src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java rename src/main/java/eu/m724/tweaks/redstone/{RedstoneManager.java => RedstoneModule.java} (76%) delete mode 100644 src/main/java/eu/m724/tweaks/sleep/SleepManager.java create mode 100644 src/main/java/eu/m724/tweaks/sleep/SleepModule.java rename src/main/java/eu/m724/tweaks/swing/{SwingManager.java => SwingModule.java} (85%) rename src/main/java/eu/m724/tweaks/updater/{UpdaterManager.java => UpdaterModule.java} (68%) rename src/main/java/eu/m724/tweaks/worldborder/{WorldBorderExpander.java => WorldBorderExpandModule.java} (78%) create mode 100644 src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java delete mode 100644 src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java diff --git a/pom.xml b/pom.xml index 45ceefd..cec41b0 100644 --- a/pom.xml +++ b/pom.xml @@ -17,8 +17,8 @@ 21 UTF-8 - v1_21_R1 - 1.21.1 + v1_21_R2 + 1.21.3 ${project.minecraft.version}-R0.1-SNAPSHOT diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java index 2b91bee..d74b63c 100644 --- a/src/main/java/eu/m724/tweaks/DebugLogger.java +++ b/src/main/java/eu/m724/tweaks/DebugLogger.java @@ -12,36 +12,50 @@ import java.util.logging.Logger; public class DebugLogger { static Logger logger; - public static void info(String message) { - log(Level.INFO, message); + public static void info(String message, Object... format) { + log(Level.INFO, message, format); } - public static void warning(String message) { - log(Level.WARNING, message); + public static void warning(String message, Object... format) { + log(Level.WARNING, message, format); } - public static void severe(String message) { - log(Level.SEVERE, message); + public static void severe(String message, Object... format) { + log(Level.SEVERE, message, format); } - public static void fine(String message) { - log(Level.FINE, message); + public static void fine(String message, Object... format) { + log(Level.FINE, message, format); } - private static void log(Level level, String message) { + public static void finer(String message, Object... format) { + log(Level.FINER, message, format); + } + + private static void log(Level level, String message, Object... format) { if (logger.getLevel().intValue() > level.intValue()) return; var caller = Thread.currentThread().getStackTrace()[3].getClassName(); + if (caller.equals(TweaksModule.class.getName())) { + var pcaller = Thread.currentThread().getStackTrace()[4].getClassName(); + if (pcaller.endsWith("Module")) + caller = pcaller; + } + if (caller.startsWith("eu.m724.tweaks.")) caller = caller.substring(15); - message = "[" + caller + "] " + message; + message = "[" + caller + "] " + message.formatted(format); if (level.intValue() < Level.INFO.intValue()) { // levels below info are never logged even if set for some reason - level = Level.INFO; // colors text gray (cyan is close to gray) - message = "\033[36m" + message + "\033[39m"; + if (level == Level.FINE) { + message = "\033[38;5;250m" + message + "\033[39m"; + } else { + message = "\033[38;5;245m" + message + "\033[39m"; + } + level = Level.INFO; } logger.log(level, message); diff --git a/src/main/java/eu/m724/tweaks/TweaksModule.java b/src/main/java/eu/m724/tweaks/TweaksModule.java new file mode 100644 index 0000000..a75bdea --- /dev/null +++ b/src/main/java/eu/m724/tweaks/TweaksModule.java @@ -0,0 +1,87 @@ +/* + * 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; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import org.bukkit.command.CommandExecutor; +import org.bukkit.event.Listener; + +import java.lang.reflect.InvocationTargetException; +import java.util.function.Consumer; + +public abstract class TweaksModule { + protected abstract void onInit(); + + void init() { + var name = getClass().getSimpleName(); + DebugLogger.finer("Initializing " + name); + long start = System.nanoTime(); + + this.onInit(); + + long end = System.nanoTime(); + DebugLogger.fine("Initialized %s in %d µs", name, (end - start) / 1000); + } + + // TODO not static maybe? + protected TweaksPlugin getPlugin() { + return TweaksPlugin.getInstance(); + } + + protected TweaksConfig getConfig() { + return TweaksConfig.getConfig(); + } + + protected void registerEvents(Listener listener) { + DebugLogger.finer("Registered listener: " + listener.getClass().getName()); + getPlugin().getServer().getPluginManager().registerEvents(listener, getPlugin()); + } + + protected void onPacketSend(PacketType packetType, Consumer consumer) { + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) { + @Override + public void onPacketSending(PacketEvent event) { + consumer.accept(event); + } + }); + + DebugLogger.finer("Registered packet send: " + packetType.name()); + } + + protected void onPacketReceive(PacketType packetType, Consumer consumer) { + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) { + @Override + public void onPacketReceiving(PacketEvent event) { + consumer.accept(event); + } + }); + + DebugLogger.finer("Registered packet receive: " + packetType.name()); + } + + protected void registerCommand(String command, CommandExecutor executor) { + getPlugin().getCommand(command).setExecutor(executor); + DebugLogger.finer("Registered command: " + command); + } + + public static T init(Class clazz) { + T module; + try { + module = clazz.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + + module.init(); + + return module; + } +} diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index b0abd9a..42975fc 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -7,33 +7,36 @@ package eu.m724.tweaks; import eu.m724.mstats.MStatsPlugin; -import eu.m724.tweaks.alert.AlertManager; -import eu.m724.tweaks.auth.AuthManager; -import eu.m724.tweaks.chat.ChatManager; -import eu.m724.tweaks.door.DoorKnockListener; -import eu.m724.tweaks.door.DoorOpenListener; -import eu.m724.tweaks.full.FullListener; -import eu.m724.tweaks.hardcore.HardcoreManager; -import eu.m724.tweaks.killswitch.KillswitchManager; -import eu.m724.tweaks.knockback.KnockbackListener; -import eu.m724.tweaks.motd.MotdManager; +import eu.m724.tweaks.alert.AlertModule; +import eu.m724.tweaks.auth.AuthModule; +import eu.m724.tweaks.chat.ChatModule; +import eu.m724.tweaks.door.DoorKnockModule; +import eu.m724.tweaks.door.DoorOpenModule; +import eu.m724.tweaks.full.FullModule; +import eu.m724.tweaks.hardcore.HardcoreModule; +import eu.m724.tweaks.killswitch.KillswitchModule; +import eu.m724.tweaks.knockback.KnockbackModule; +import eu.m724.tweaks.motd.MotdModule; import eu.m724.tweaks.ping.F3NameListener; import eu.m724.tweaks.ping.PingChecker; -import eu.m724.tweaks.pomodoro.PomodoroManager; -import eu.m724.tweaks.redstone.RedstoneManager; -import eu.m724.tweaks.sleep.SleepManager; -import eu.m724.tweaks.swing.SwingManager; -import eu.m724.tweaks.updater.UpdaterManager; -import eu.m724.tweaks.worldborder.WorldBorderExpander; -import eu.m724.tweaks.worldborder.WorldBorderHider; +import eu.m724.tweaks.pomodoro.PomodoroModule; +import eu.m724.tweaks.redstone.RedstoneModule; +import eu.m724.tweaks.sleep.SleepModule; +import eu.m724.tweaks.swing.SwingModule; +import eu.m724.tweaks.updater.UpdaterModule; +import eu.m724.tweaks.worldborder.WorldBorderExpandModule; +import eu.m724.tweaks.worldborder.WorldBorderHideModule; import java.util.Locale; import java.util.logging.Level; public class TweaksPlugin extends MStatsPlugin { + private static TweaksPlugin INSTANCE; + @Override public void onEnable() { long start = System.nanoTime(); + INSTANCE = this; if (getServer().getPluginManager().getPlugin("ProtocolLib") == null) { getLogger().severe("ProtocolLib is required for this plugin."); @@ -46,37 +49,36 @@ public class TweaksPlugin extends MStatsPlugin { getLogger().setLevel(config.debug() ? Level.FINEST : Level.INFO); DebugLogger.logger = getLogger(); - DebugLogger.fine("Debug enabled. There may be performance issues."); - DebugLogger.fine("Enabling Language"); + if (config.debug()) { + DebugLogger.warning("Debug harms performance"); + } + + DebugLogger.fine("Language"); new Language(Locale.of(config.locale())); // TODO DebugLogger.fine(Language.getString("languageNotice", Language.getString("language"), Language.getString("languageEnglish"))); /* start modules */ if (config.worldborderHide()) { - DebugLogger.fine("Enabling Worldborder hide"); - new WorldBorderHider().init(this); + TweaksModule.init(WorldBorderHideModule.class); } if (config.worldborderExpand()) { - DebugLogger.fine("Enabling Worldborder expand"); - new WorldBorderExpander().init(this); + TweaksModule.init(WorldBorderExpandModule.class); + } if (config.chatEnabled()) { - DebugLogger.fine("Enabling Chat"); - new ChatManager(this).init(getCommand("chat"), getCommand("chatmanage")); + TweaksModule.init(ChatModule.class); } if (config.doorKnocking()) { - DebugLogger.fine("Enabling Door knock"); - getServer().getPluginManager().registerEvents(new DoorKnockListener(), this); + TweaksModule.init(DoorKnockModule.class); } if (config.doorDoubleOpen()) { - DebugLogger.fine("Enabling Door double open"); - getServer().getPluginManager().registerEvents(new DoorOpenListener(), this); + TweaksModule.init(DoorOpenModule.class); } if (config.brandEnabled()) { @@ -88,57 +90,45 @@ public class TweaksPlugin extends MStatsPlugin { new PingChecker(this).init(getCommand("ping")); if (config.motdEnabled()) { - DebugLogger.fine("Enabling MOTD"); - new MotdManager(this).init(); + TweaksModule.init(MotdModule.class); } if (config.pomodoroEnabled()) { - DebugLogger.fine("Enabling Pomodoro"); - new PomodoroManager(this).init(getCommand("pomodoro")); + TweaksModule.init(PomodoroModule.class); } if (config.updaterEnabled()) { - DebugLogger.fine("Enabling Updater"); - new UpdaterManager(this).init(getCommand("updates")); + TweaksModule.init(UpdaterModule.class); } if (config.hardcoreEnabled()) { - DebugLogger.fine("Enabling Hardcore"); - new HardcoreManager().init(this); + TweaksModule.init(HardcoreModule.class); } if (config.sleepEnabled()) { - DebugLogger.fine("Enabling Sleep"); - new SleepManager().init(this); + TweaksModule.init(SleepModule.class); } if (config.authEnabled()) { - DebugLogger.fine("Enabling Auth"); - new AuthManager(this).init(getCommand("tauth")); + TweaksModule.init(AuthModule.class); } - DebugLogger.fine("Enabling Alert"); - new AlertManager(this).init(getCommand("emergencyalert")); + TweaksModule.init(AlertModule.class); - DebugLogger.fine("Enabling Full"); - getServer().getPluginManager().registerEvents(new FullListener(), this); + TweaksModule.init(FullModule.class); if (config.redstoneEnabled()) { - DebugLogger.fine("Enabling Redstone"); - new RedstoneManager(this).init(getCommand("retstone")); + TweaksModule.init(RedstoneModule.class); } - DebugLogger.fine("Enabling Knockback"); - new KnockbackListener(this); + TweaksModule.init(KnockbackModule.class); if (config.killswitchEnabled()) { - DebugLogger.fine("Enabling Killswitch"); - new KillswitchManager(this).init(getCommand("servkill")); + TweaksModule.init(KillswitchModule.class); } if (config.swingEnabled()) { - DebugLogger.fine("Enabling Swing"); - new SwingManager(this).init(); + TweaksModule.init(SwingModule.class); } /* end modules */ @@ -154,4 +144,8 @@ public class TweaksPlugin extends MStatsPlugin { public boolean hasResource(String resource) { return this.getClassLoader().getResource(resource) != null; } + + public static TweaksPlugin getInstance() { + return INSTANCE; + } } diff --git a/src/main/java/eu/m724/tweaks/alert/AlertCommand.java b/src/main/java/eu/m724/tweaks/alert/AlertCommand.java index e5748a7..2a5d821 100644 --- a/src/main/java/eu/m724/tweaks/alert/AlertCommand.java +++ b/src/main/java/eu/m724/tweaks/alert/AlertCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -20,9 +20,9 @@ public class AlertCommand implements CommandExecutor { private List pending; private long when; - private final AlertManager manager; + private final AlertModule manager; - public AlertCommand(AlertManager manager) { + public AlertCommand(AlertModule manager) { this.manager = manager; } @@ -51,7 +51,7 @@ public class AlertCommand implements CommandExecutor { } else if (args[0].equalsIgnoreCase("confirm")) { sender.sendMessage("CONFIRM must be in all caps"); } else if (args[0].equalsIgnoreCase("cancel")) { - if (AlertManager.current != null) { + if (AlertModule.current != null) { manager.stop(); sender.sendMessage("Cancelled alert"); } else if (pending != null) { @@ -86,7 +86,7 @@ public class AlertCommand implements CommandExecutor { if (pending != null) { when = System.currentTimeMillis(); - if (AlertManager.current != null) { + if (AlertModule.current != null) { sender.sendMessage("Broadcasting a new alert will cancel the currently active one"); } sender.sendMessage("Please confirm broadcast with /emergencyalert CONFIRM within 15 seconds"); diff --git a/src/main/java/eu/m724/tweaks/alert/AlertManager.java b/src/main/java/eu/m724/tweaks/alert/AlertManager.java deleted file mode 100644 index f2b72d9..0000000 --- a/src/main/java/eu/m724/tweaks/alert/AlertManager.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2024 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.alert; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import eu.m724.tweaks.TweaksPlugin; -import org.bukkit.command.PluginCommand; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitTask; - -import java.util.HashMap; -import java.util.Map; - -public class AlertManager { - private final TweaksPlugin plugin; - - private BukkitTask notifyTask; - static Alert current; - static Map pages = new HashMap<>(); - - public AlertManager(TweaksPlugin plugin) { - this.plugin = plugin; - } - - public void init(PluginCommand command) { - command.setExecutor(new AlertCommand(this)); - - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Play.Client.ENCHANT_ITEM - ) { - @Override - public void onPacketReceiving(PacketEvent event) { - if (current == null) return; - if (!current.isOpen(event.getPlayer())) return; - - PacketContainer packet = event.getPacket(); - - int windowId, buttonId; - windowId = packet.getIntegers().read(0); - buttonId = packet.getIntegers().read(1); - - var page = pages.getOrDefault(event.getPlayer(),1); - - if (buttonId == 1) { // prev page - page--; - } else if (buttonId == 2) { // nextc page - page++; - } else { - return; - } - - pages.put(event.getPlayer(), page); - var npacket = new PacketContainer(PacketType.Play.Server.WINDOW_DATA); - npacket.getIntegers().write(0, windowId); - npacket.getIntegers().write(1, 0); - npacket.getIntegers().write(2, page); - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), npacket); - } - }); - } - - public Alert start(String... content) { - stop(); - current = new Alert(content); - notifyTask = new AlertRunnable(current, v -> this.stop()).runTaskTimer(plugin, 0, 10); - return current; - } - - public void stop() { - if (current == null) return; - for (Player player : plugin.getServer().getOnlinePlayers()) { - if (current.isOpen(player)) - player.closeInventory(); - } - pages.clear(); - notifyTask.cancel(); - current = null; - } -} diff --git a/src/main/java/eu/m724/tweaks/alert/AlertModule.java b/src/main/java/eu/m724/tweaks/alert/AlertModule.java new file mode 100644 index 0000000..b7df6a9 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/alert/AlertModule.java @@ -0,0 +1,74 @@ +/* + * 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.alert; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import eu.m724.tweaks.TweaksModule; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import java.util.HashMap; +import java.util.Map; + +public class AlertModule extends TweaksModule { + private BukkitTask notifyTask; + static Alert current; + static Map pages = new HashMap<>(); + + @Override + protected void onInit() { + registerCommand("emergencyalert", new AlertCommand(this)); + + onPacketReceive(PacketType.Play.Client.ENCHANT_ITEM, (event) -> { + if (current == null) return; + if (!current.isOpen(event.getPlayer())) return; + + PacketContainer packet = event.getPacket(); + + int windowId, buttonId; + windowId = packet.getIntegers().read(0); + buttonId = packet.getIntegers().read(1); + + var page = pages.getOrDefault(event.getPlayer(),1); + + if (buttonId == 1) { // prev page + page--; + } else if (buttonId == 2) { // nextc page + page++; + } else { + return; + } + + pages.put(event.getPlayer(), page); + var npacket = new PacketContainer(PacketType.Play.Server.WINDOW_DATA); + npacket.getIntegers().write(0, windowId); + npacket.getIntegers().write(1, 0); + npacket.getIntegers().write(2, page); + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), npacket); + }); + } + + public Alert start(String... content) { + stop(); + current = new Alert(content); + notifyTask = new AlertRunnable(current, v -> this.stop()).runTaskTimer(getPlugin(), 0, 10); + return current; + } + + public void stop() { + if (current == null) return; + for (Player player : getPlugin().getServer().getOnlinePlayers()) { + if (current.isOpen(player)) + player.closeInventory(); + } + pages.clear(); + notifyTask.cancel(); + current = null; + } +} diff --git a/src/main/java/eu/m724/tweaks/auth/AuthManager.java b/src/main/java/eu/m724/tweaks/auth/AuthManager.java deleted file mode 100644 index 402b376..0000000 --- a/src/main/java/eu/m724/tweaks/auth/AuthManager.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2024 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.auth; - -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.Plugin; - -public class AuthManager { - private final AuthStorage authStorage; - private final Plugin plugin; - - public AuthManager(Plugin plugin) { - this.plugin = plugin; - this.authStorage = new AuthStorage(plugin); - } - - public void init(PluginCommand command) { - plugin.getServer().getPluginManager().registerEvents(new AuthListener(authStorage), plugin); - command.setExecutor(new AuthCommands(authStorage)); - } -} diff --git a/src/main/java/eu/m724/tweaks/auth/AuthModule.java b/src/main/java/eu/m724/tweaks/auth/AuthModule.java new file mode 100644 index 0000000..43d0fcf --- /dev/null +++ b/src/main/java/eu/m724/tweaks/auth/AuthModule.java @@ -0,0 +1,19 @@ +/* + * 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.auth; + +import eu.m724.tweaks.TweaksModule; + +public class AuthModule extends TweaksModule { + @Override + protected void onInit() { + var authStorage = new AuthStorage(getPlugin()); + + registerEvents(new AuthListener(authStorage)); + registerCommand("tauth", new AuthCommands(authStorage)); + } +} diff --git a/src/main/java/eu/m724/tweaks/chat/ChatCommands.java b/src/main/java/eu/m724/tweaks/chat/ChatCommands.java index 09e19b7..1ed2180 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatCommands.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -21,9 +21,9 @@ import java.util.Arrays; import java.util.stream.Collectors; public class ChatCommands implements CommandExecutor { - private final ChatManager manager; + private final ChatModule manager; - public ChatCommands(ChatManager manager) { + public ChatCommands(ChatModule manager) { this.manager = manager; } @@ -94,9 +94,9 @@ public class ChatCommands implements CommandExecutor { ChatRoom newRoom = manager.createChatRoom(argument, null, player); sender.sendMessage("Created a chat room. Join it: /c " + newRoom.id); sender.sendMessage("You might also want to protect it with a password: /cm setpassword"); - } catch (ChatManager.InvalidIdException e) { + } catch (ChatModule.InvalidIdException e) { sender.sendMessage("ID is invalid: " + e.getMessage()); - } catch (ChatManager.ChatRoomExistsException e) { + } catch (ChatModule.ChatRoomExistsException e) { sender.sendMessage("Room %s already exists".formatted(argument)); } catch (IOException e) { sender.sendMessage("Failed to create room"); diff --git a/src/main/java/eu/m724/tweaks/chat/ChatListener.java b/src/main/java/eu/m724/tweaks/chat/ChatListener.java index f114e58..83dc4c2 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatListener.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -25,13 +25,14 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; public class ChatListener implements Listener { - private final ChatManager chatManager; + private final ChatModule chatModule; private final String defaultRoom = TweaksConfig.getConfig().chatDefaultName(); private final boolean localEvents = TweaksConfig.getConfig().chatLocalEvents(); private final int radius; - public ChatListener(ChatManager chatManager) { - this.chatManager = chatManager; + public ChatListener(ChatModule chatModule) { + this.chatModule = chatModule; + if (TweaksConfig.getConfig().chatRadius() < 0) { radius = 0; } else { @@ -52,7 +53,7 @@ public class ChatListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - ChatRoom chatRoom = chatManager.getPlayerChatRoom(player); + ChatRoom chatRoom = chatModule.getPlayerChatRoom(player); if (localEvents) { var cb = new ComponentBuilder() @@ -77,7 +78,7 @@ public class ChatListener implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); - ChatRoom chatRoom = chatManager.removePlayer(player); + ChatRoom chatRoom = chatModule.removePlayer(player); if (localEvents) { var cb = new ComponentBuilder() @@ -103,7 +104,7 @@ public class ChatListener implements Listener { public void onPlayerDeath(PlayerDeathEvent event) { if (localEvents) { Player player = event.getEntity(); - ChatRoom chatRoom = chatManager.getPlayerChatRoom(player); + ChatRoom chatRoom = chatModule.getPlayerChatRoom(player); // would be easier on Paper but this is not Paper BaseComponent deathMessage = ComponentSerializer.deserialize(Component.Serializer.toJson(((CraftPlayer)player).getHandle().getCombatTracker().getDeathMessage(), CraftRegistry.getMinecraftRegistry())); @@ -124,7 +125,7 @@ public class ChatListener implements Listener { // broadcast to killer if available if (player.getLastDamageCause().getDamageSource().getCausingEntity() instanceof Player killer) { - ChatRoom chatRoom2 = chatManager.getPlayerChatRoom(killer); + ChatRoom chatRoom2 = chatModule.getPlayerChatRoom(killer); if (chatRoom != chatRoom2) { if (proximityFor(chatRoom)) { chatRoom2.broadcastNear(killer.getLocation(), radius, component); @@ -142,7 +143,7 @@ public class ChatListener implements Listener { @EventHandler public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { Player player = event.getPlayer(); - ChatRoom chatRoom = chatManager.getPlayerChatRoom(player); + ChatRoom chatRoom = chatModule.getPlayerChatRoom(player); String message = event.getMessage(); var component = new ComponentBuilder() diff --git a/src/main/java/eu/m724/tweaks/chat/ChatManager.java b/src/main/java/eu/m724/tweaks/chat/ChatModule.java similarity index 87% rename from src/main/java/eu/m724/tweaks/chat/ChatManager.java rename to src/main/java/eu/m724/tweaks/chat/ChatModule.java index 04d1a84..eaad314 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatManager.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatModule.java @@ -1,50 +1,43 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.chat; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.TweaksModule; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; -import org.bukkit.command.PluginCommand; import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; -import org.bukkit.plugin.Plugin; import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class ChatManager { - private final Plugin plugin; - private final NamespacedKey chatRoomKey; - private final String defaultRoom; +public class ChatModule extends TweaksModule { + private final NamespacedKey chatRoomKey = new NamespacedKey(getPlugin(), "chatRoom"); + private final String defaultRoom = getConfig().chatDefaultName(); private final Map playerMap = new HashMap<>(); private final Map roomIdMap = new HashMap<>(); - public ChatManager(Plugin plugin) { - this.plugin = plugin; - this.chatRoomKey = new NamespacedKey(plugin, "chatRoom"); - this.defaultRoom = TweaksConfig.getConfig().chatDefaultName(); - } - public void init(PluginCommand chatCommand, PluginCommand chatManageCommand) { - if (plugin.getServer().isEnforcingSecureProfiles()) { + @Override + protected void onInit() { + if (getPlugin().getServer().isEnforcingSecureProfiles()) { throw new RuntimeException("Please disable enforce-secure-profile in server.properties to use chatrooms"); } getById(defaultRoom); - plugin.getServer().getPluginManager().registerEvents(new ChatListener(this), plugin); + registerEvents(new ChatListener(this)); var chatCommands = new ChatCommands(this); - chatCommand.setExecutor(chatCommands); - chatManageCommand.setExecutor(chatCommands); + registerCommand("chat", chatCommands); + registerCommand("chatmanage", chatCommands); } /** diff --git a/src/main/java/eu/m724/tweaks/compass/CompassManager.java b/src/main/java/eu/m724/tweaks/compass/CompassManager.java deleted file mode 100644 index 0ba9113..0000000 --- a/src/main/java/eu/m724/tweaks/compass/CompassManager.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2024 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.compass; - -import org.bukkit.plugin.Plugin; - -public class CompassManager { - private final Plugin plugin; - - public CompassManager(Plugin plugin) { - this.plugin = plugin; - } - - public void init() { - plugin.getServer().getPluginManager().registerEvents(new CompassListener(), plugin); - } -} diff --git a/src/main/java/eu/m724/tweaks/compass/CompassListener.java b/src/main/java/eu/m724/tweaks/compass/CompassModule.java similarity index 92% rename from src/main/java/eu/m724/tweaks/compass/CompassListener.java rename to src/main/java/eu/m724/tweaks/compass/CompassModule.java index f1873cd..23dfcf7 100644 --- a/src/main/java/eu/m724/tweaks/compass/CompassListener.java +++ b/src/main/java/eu/m724/tweaks/compass/CompassModule.java @@ -1,12 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.compass; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.TweaksModule; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.ComponentBuilder; @@ -25,9 +25,9 @@ import java.util.LinkedHashMap; import java.util.Map; // TODO dimension check -public class CompassListener implements Listener { - private final int precision = TweaksConfig.getConfig().compassPrecision(); // degrees every point - private final int width = TweaksConfig.getConfig().compassWidth(); // points left to right +public class CompassModule extends TweaksModule implements Listener { + private final int precision = getConfig().compassPrecision(); // degrees every point + private final int width = getConfig().compassWidth(); // points left to right private final Map points = Map.of( 0, ChatColor.DARK_GRAY + "S", @@ -36,6 +36,11 @@ public class CompassListener implements Listener { 270, ChatColor.DARK_GRAY + "E" ); + @Override + protected void onInit() { + registerEvents(this); + } + @EventHandler public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { if (event.getMainHandItem().getType() == Material.COMPASS || event.getOffHandItem().getType() == Material.COMPASS) { diff --git a/src/main/java/eu/m724/tweaks/door/DoorKnockListener.java b/src/main/java/eu/m724/tweaks/door/DoorKnockModule.java similarity index 90% rename from src/main/java/eu/m724/tweaks/door/DoorKnockListener.java rename to src/main/java/eu/m724/tweaks/door/DoorKnockModule.java index b9c718d..2627c18 100644 --- a/src/main/java/eu/m724/tweaks/door/DoorKnockListener.java +++ b/src/main/java/eu/m724/tweaks/door/DoorKnockModule.java @@ -1,11 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.door; +import eu.m724.tweaks.TweaksModule; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -22,7 +23,12 @@ import org.bukkit.util.RayTraceResult; import java.util.concurrent.ThreadLocalRandom; -public class DoorKnockListener implements Listener { +public class DoorKnockModule extends TweaksModule implements Listener { + @Override + protected void onInit() { + registerEvents(this); + } + @EventHandler public void onBlockDamageAbort(BlockDamageAbortEvent event) { Block block = event.getBlock(); diff --git a/src/main/java/eu/m724/tweaks/door/DoorOpenListener.java b/src/main/java/eu/m724/tweaks/door/DoorOpenModule.java similarity index 92% rename from src/main/java/eu/m724/tweaks/door/DoorOpenListener.java rename to src/main/java/eu/m724/tweaks/door/DoorOpenModule.java index 1b431eb..e6773df 100644 --- a/src/main/java/eu/m724/tweaks/door/DoorOpenListener.java +++ b/src/main/java/eu/m724/tweaks/door/DoorOpenModule.java @@ -1,11 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.door; +import eu.m724.tweaks.TweaksModule; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -15,7 +16,11 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -public class DoorOpenListener implements Listener { +public class DoorOpenModule extends TweaksModule implements Listener { + @Override + protected void onInit() { + registerEvents(this); + } @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { @@ -71,5 +76,4 @@ public class DoorOpenListener implements Listener { location.getBlock().setBlockData(nextDoor); } } - } diff --git a/src/main/java/eu/m724/tweaks/full/FullListener.java b/src/main/java/eu/m724/tweaks/full/FullModule.java similarity index 71% rename from src/main/java/eu/m724/tweaks/full/FullListener.java rename to src/main/java/eu/m724/tweaks/full/FullModule.java index 29f4572..8b40269 100644 --- a/src/main/java/eu/m724/tweaks/full/FullListener.java +++ b/src/main/java/eu/m724/tweaks/full/FullModule.java @@ -1,16 +1,22 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.full; +import eu.m724.tweaks.TweaksModule; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerLoginEvent; -public class FullListener implements Listener { +public class FullModule extends TweaksModule implements Listener { + @Override + protected void onInit() { + registerEvents(this); + } + @EventHandler public void onPlayerLogin(PlayerLoginEvent event) { if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && event.getPlayer().hasPermission("tweaks724.bypass-full")) { diff --git a/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java b/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java deleted file mode 100644 index e03179e..0000000 --- a/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java +++ /dev/null @@ -1,60 +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.hardcore; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; -import net.minecraft.world.level.levelgen.RandomSupport; -import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus; -import org.bukkit.plugin.Plugin; - -import java.math.BigDecimal; -import java.math.BigInteger; - -// how we do it is much faster than any Random -public class HardcoreManager { - private final double chance = TweaksConfig.getConfig().hardcoreChance(); - - private final long chanceLong = BigInteger.valueOf(Long.MIN_VALUE) - .add( - new BigDecimal( - BigInteger.valueOf(Long.MAX_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE)) - ).multiply( - BigDecimal.valueOf(chance) - ).toBigInteger() - ).longValue(); - - private final Xoroshiro128PlusPlus rng = new Xoroshiro128PlusPlus( - RandomSupport.generateUniqueSeed(), - RandomSupport.generateUniqueSeed() - ); - - public void init(Plugin plugin) { - DebugLogger.fine("Chance long: " + chanceLong); - - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Play.Server.LOGIN - ) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); - - if (rng.nextLong() < chanceLong) - // the "is hardcore" boolean https://wiki.vg/Protocol#Login_.28play.29 - packet.getBooleans().write(0, true); - } - }); - } -} diff --git a/src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java b/src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java new file mode 100644 index 0000000..b0df9a4 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java @@ -0,0 +1,52 @@ +/* + * 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.hardcore; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksModule; +import net.minecraft.world.level.levelgen.RandomSupport; +import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus; + +import java.math.BigDecimal; +import java.math.BigInteger; + +// how we do it is much faster than any Random +public class HardcoreModule extends TweaksModule { + private final Xoroshiro128PlusPlus rng; + private final long chanceLong; + + public HardcoreModule() { + this.rng = new Xoroshiro128PlusPlus( + RandomSupport.generateUniqueSeed(), + RandomSupport.generateUniqueSeed() + ); + + this.chanceLong = BigInteger.valueOf(Long.MIN_VALUE) + .add( + new BigDecimal( + BigInteger.valueOf(Long.MAX_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE)) + ).multiply( + BigDecimal.valueOf(getConfig().hardcoreChance()) + ).toBigInteger() + ).longValue(); + } + + @Override + protected void onInit() { + DebugLogger.fine("Chance long: " + chanceLong); + + onPacketSend(PacketType.Play.Server.LOGIN, (event) -> { + PacketContainer packet = event.getPacket(); + + if (rng.nextLong() < chanceLong) + // the "is hardcore" boolean https://wiki.vg/Protocol#Login_.28play.29 + packet.getBooleans().write(0, true); + }); + } +} diff --git a/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java b/src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java similarity index 82% rename from src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java rename to src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java index c16f75d..b511ab9 100644 --- a/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java +++ b/src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java @@ -10,13 +10,10 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; -import eu.m724.tweaks.TweaksPlugin; +import eu.m724.tweaks.TweaksModule; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -27,17 +24,12 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; -public class KillswitchManager implements CommandExecutor, HttpHandler { - private final Plugin plugin; +public class KillswitchModule extends TweaksModule implements CommandExecutor, HttpHandler { private final Ratelimit ratelimit = new Ratelimit(); private byte[] secret; private String secretEncoded; - public KillswitchManager(Plugin plugin) { - this.plugin = plugin; - } - private void loadKey(File file) { if (file.exists()) { try { @@ -63,15 +55,16 @@ public class KillswitchManager implements CommandExecutor, HttpHandler { this.secretEncoded = Base64.getEncoder().encodeToString(secret); } - public void init(PluginCommand serverKillCommand) { - serverKillCommand.setExecutor(this); + @Override + protected void onInit() { + registerCommand("servkill", this); - if (TweaksConfig.getConfig().killswitchListen() != null) { - loadKey(new File(plugin.getDataFolder(), "storage/killswitch key")); + if (getConfig().killswitchListen() != null) { + loadKey(new File(getPlugin().getDataFolder(), "storage/killswitch key")); - ratelimit.runTaskTimerAsynchronously(plugin, 0, 20 * 300); + ratelimit.runTaskTimerAsynchronously(getPlugin(), 0, 20 * 300); - var listenAddress = TweaksConfig.getConfig().killswitchListen().split(":"); + var listenAddress = getConfig().killswitchListen().split(":"); InetSocketAddress bindAddress; if (listenAddress.length == 1) { bindAddress = new InetSocketAddress(Integer.parseInt(listenAddress[0])); diff --git a/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java b/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java similarity index 85% rename from src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java rename to src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java index 3239d5c..6b56ffb 100644 --- a/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java +++ b/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java @@ -7,22 +7,22 @@ package eu.m724.tweaks.knockback; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.TweaksModule; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityKnockbackByEntityEvent; -import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import java.util.HashMap; import java.util.Map; -public class KnockbackListener implements Listener { +public class KnockbackModule extends TweaksModule implements Listener { private final Map modifiers = new HashMap<>(); - public KnockbackListener(Plugin plugin) { - TweaksConfig.getConfig().knockbackModifiers().forEach((k, v) -> { + @Override + protected void onInit() { + getConfig().knockbackModifiers().forEach((k, v) -> { EntityType type; double mod; @@ -50,7 +50,7 @@ public class KnockbackListener implements Listener { }); if (!modifiers.isEmpty()) - plugin.getServer().getPluginManager().registerEvents(this, plugin); + registerEvents(this); } @EventHandler diff --git a/src/main/java/eu/m724/tweaks/motd/MotdManager.java b/src/main/java/eu/m724/tweaks/motd/MotdModule.java similarity index 54% rename from src/main/java/eu/m724/tweaks/motd/MotdManager.java rename to src/main/java/eu/m724/tweaks/motd/MotdModule.java index 0ac9c79..03043fb 100644 --- a/src/main/java/eu/m724/tweaks/motd/MotdManager.java +++ b/src/main/java/eu/m724/tweaks/motd/MotdModule.java @@ -7,7 +7,6 @@ package eu.m724.tweaks.motd; import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.*; import com.comphenix.protocol.reflect.StructureModifier; import com.google.gson.JsonElement; @@ -15,14 +14,13 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; -import eu.m724.tweaks.TweaksPlugin; +import eu.m724.tweaks.TweaksModule; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.SharedConstants; import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.status.ServerStatus; -import org.bukkit.plugin.Plugin; import java.io.File; import java.io.IOException; @@ -31,34 +29,29 @@ import java.util.Arrays; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; -public class MotdManager { - private final TweaksPlugin plugin; - +public class MotdModule extends TweaksModule { private Component[] motds; - public MotdManager(TweaksPlugin plugin) { - this.plugin = plugin; - } - - public void init() { + @Override + protected void onInit() { // TODO adding more MOTD features would require checking whether to enable set String motdSetName = TweaksConfig.getConfig().motdSet(); String motdSetPath = "motd sets/" + motdSetName + ".txt"; - File motdSetsFile = new File(plugin.getDataFolder(), motdSetPath); + File motdSetsFile = new File(getPlugin().getDataFolder(), motdSetPath); // create "motd sets" directory motdSetsFile.getParentFile().mkdirs(); // if this is a builtin set - if (!motdSetsFile.exists() && plugin.hasResource(motdSetPath)) - plugin.saveResource(motdSetPath, false); + if (!motdSetsFile.exists() && getPlugin().hasResource(motdSetPath)) + getPlugin().saveResource(motdSetPath, false); if (!motdSetsFile.exists()) { throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(motdSetName)); } - String fileContent = null; + String fileContent; try { fileContent = Files.readString(motdSetsFile.toPath()); } catch (IOException e) { @@ -73,9 +66,9 @@ public class MotdManager { try { json = JsonParser.parseString(entry); - DebugLogger.fine("JSON line: " + entry); + DebugLogger.finer("JSON line: %s...", entry.substring(0, Math.min(entry.length(), 10))); } catch (JsonParseException e) { - DebugLogger.fine("Not a JSON line: " + entry); + DebugLogger.finer("JSON line: %s...", entry.substring(0, Math.min(entry.length(), 10))); } if (json == null) { @@ -86,40 +79,29 @@ public class MotdManager { }) .toArray(Component[]::new); - registerListener(plugin); - } + onPacketSend(PacketType.Status.Server.SERVER_INFO, (event) -> { + PacketContainer packet = event.getPacket(); - private void registerListener(Plugin plugin) { - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Status.Server.SERVER_INFO - ) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); + Component motd = motds[ThreadLocalRandom.current().nextInt(motds.length)]; - Component motd = motds[ThreadLocalRandom.current().nextInt(motds.length)]; + ServerStatus serverStatus = (ServerStatus) packet.getStructures().read(0).getHandle(); - ServerStatus serverStatus = (ServerStatus) packet.getStructures().read(0).getHandle(); + /* this: + * removes server mod prefix (Paper, Spigot, any brand) + * hides players + */ + ServerStatus newStatus = new ServerStatus( + motd, + Optional.empty(), + Optional.of(new ServerStatus.Version( + SharedConstants.getCurrentVersion().getName(), + SharedConstants.getProtocolVersion() + )), + serverStatus.favicon(), + false + ); - /* this: - * removes server mod prefix (Paper, Spigot, any brand) - * hides players - */ - ServerStatus newStatus = new ServerStatus( - motd, - Optional.empty(), - Optional.of(new ServerStatus.Version( - SharedConstants.getCurrentVersion().getName(), - SharedConstants.getProtocolVersion() - )), - serverStatus.favicon(), - false - ); - - packet.getStructures().write(0, new InternalStructure(newStatus, new StructureModifier<>(ServerStatus.class))); - } + packet.getStructures().write(0, new InternalStructure(newStatus, new StructureModifier<>(ServerStatus.class))); }); } } diff --git a/src/main/java/eu/m724/tweaks/ping/PingChecker.java b/src/main/java/eu/m724/tweaks/ping/PingChecker.java index 41e95ab..e43ef04 100644 --- a/src/main/java/eu/m724/tweaks/ping/PingChecker.java +++ b/src/main/java/eu/m724/tweaks/ping/PingChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -9,8 +9,6 @@ package eu.m724.tweaks.ping; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; -import java.util.Objects; - public class PingChecker { private final Plugin plugin; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java deleted file mode 100644 index 0483042..0000000 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2024 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.pomodoro; - -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.Plugin; - -public class PomodoroManager { - private final Plugin plugin; - - public PomodoroManager(Plugin plugin) { - this.plugin = plugin; - } - - public void init(PluginCommand pomodoroCommand) { - plugin.getServer().getPluginManager().registerEvents(new PomodoroListener(), plugin); - new PomodoroRunnable(plugin).runTaskTimerAsynchronously(plugin, 0, 20L); - - pomodoroCommand.setExecutor(new PomodoroCommands()); - } -} diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java new file mode 100644 index 0000000..564e638 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java @@ -0,0 +1,19 @@ +/* + * 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.pomodoro; + +import eu.m724.tweaks.TweaksModule; + +public class PomodoroModule extends TweaksModule { + @Override + protected void onInit() { + registerEvents(new PomodoroListener()); + new PomodoroRunnable(getPlugin()).runTaskTimerAsynchronously(getPlugin(), 0, 20L); + + registerCommand("pomodoro", new PomodoroCommands()); + } +} diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java similarity index 76% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java rename to src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java index 2dde5bc..30cd13f 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java +++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -8,36 +8,29 @@ package eu.m724.tweaks.redstone; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.Plugin; +import eu.m724.tweaks.TweaksModule; import java.io.IOException; import java.net.*; import java.util.concurrent.Executors; import java.util.function.Consumer; -public class RedstoneManager { - private final Plugin plugin; - private final RedstoneGateways redstoneGateways; +public class RedstoneModule extends TweaksModule { + private final RedstoneGateways redstoneGateways = new RedstoneGateways(getPlugin()); private DatagramSocket socket; private RedstoneStateUpdateRunnable runnable; + @Override + protected void onInit() { + RedstoneStore.init(getPlugin()); + var gatewayItem = new GatewayItem(getPlugin()); - public RedstoneManager(Plugin plugin) { - this.plugin = plugin; - this.redstoneGateways = new RedstoneGateways(plugin); - } - - public void init(PluginCommand command) { - RedstoneStore.init(plugin); - var gatewayItem = new GatewayItem(plugin); - - plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneGateways, gatewayItem), plugin); - command.setExecutor(new RedstoneCommands(gatewayItem)); + registerEvents(new RedstoneListener(redstoneGateways, gatewayItem)); + registerCommand("retstone", new RedstoneCommands(gatewayItem)); this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways); - this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable + this.runnable.runTaskTimer(getPlugin(), 0, 20); // TODO configurable var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":"); InetSocketAddress bindAddress; @@ -52,7 +45,6 @@ public class RedstoneManager { } catch (SocketException e) { throw new RuntimeException("Starting socket", e); } - } private void initSocket(SocketAddress bindAddress) throws SocketException { @@ -96,12 +88,12 @@ public class RedstoneManager { } private void enqueueUpdate(int gatewayId, byte power) { - DebugLogger.fine("Update enqueued " + gatewayId + " " + power); + DebugLogger.finer("Update enqueued " + gatewayId + " " + power); runnable.enqueueUpdate(gatewayId, power); } private void enqueueRetrieve(int gatewayId, Consumer consumer) { - DebugLogger.fine("Retrieve enqueued " + gatewayId); + DebugLogger.finer("Retrieve enqueued " + gatewayId); runnable.enqueueRetrieve(gatewayId, consumer); } } diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepManager.java b/src/main/java/eu/m724/tweaks/sleep/SleepManager.java deleted file mode 100644 index 2aec5cf..0000000 --- a/src/main/java/eu/m724/tweaks/sleep/SleepManager.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2024 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.sleep; - -import eu.m724.tweaks.TweaksConfig; -import org.bukkit.plugin.Plugin; - -public class SleepManager { - public void init(Plugin plugin) { - plugin.getServer().getPluginManager().registerEvents(new SleepListener(), plugin); - if (!TweaksConfig.getConfig().sleepInstant()) - new TimeForwardRunnable(plugin).runTaskTimer(plugin, 0, 1); // TODO maybe not - } -} diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepModule.java b/src/main/java/eu/m724/tweaks/sleep/SleepModule.java new file mode 100644 index 0000000..d467338 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/sleep/SleepModule.java @@ -0,0 +1,19 @@ +/* + * 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.sleep; + +import eu.m724.tweaks.TweaksModule; + +public class SleepModule extends TweaksModule { + @Override + protected void onInit() { + registerEvents(new SleepListener()); + + if (!getConfig().sleepInstant()) + new TimeForwardRunnable(getPlugin()).runTaskTimer(getPlugin(), 0, 1); // TODO maybe not + } +} diff --git a/src/main/java/eu/m724/tweaks/swing/SwingManager.java b/src/main/java/eu/m724/tweaks/swing/SwingModule.java similarity index 85% rename from src/main/java/eu/m724/tweaks/swing/SwingManager.java rename to src/main/java/eu/m724/tweaks/swing/SwingModule.java index b3cd2cb..fdd2465 100644 --- a/src/main/java/eu/m724/tweaks/swing/SwingManager.java +++ b/src/main/java/eu/m724/tweaks/swing/SwingModule.java @@ -7,6 +7,7 @@ package eu.m724.tweaks.swing; import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksModule; import org.bukkit.Material; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Entity; @@ -14,29 +15,23 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.plugin.Plugin; import java.util.Arrays; import java.util.HashSet; import java.util.Set; -public class SwingManager implements Listener { - private final Plugin plugin; - +public class SwingModule extends TweaksModule implements Listener { private final Set tools = new HashSet<>(); - public SwingManager(Plugin plugin) { - this.plugin = plugin; - + @Override + protected void onInit() { Arrays.stream(Material.values()) .filter(m -> m.name().contains("SWORD")) .forEach(tools::add); - DebugLogger.fine("Tools: " + tools.size()); - } + DebugLogger.finer("Tools: " + tools.size()); - public void init() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); + registerEvents(this); } @EventHandler diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java index 03dfd1f..2f4d4d5 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java @@ -11,6 +11,7 @@ import eu.m724.tweaks.Language; import eu.m724.tweaks.updater.cache.VersionedResource; import org.bukkit.scheduler.BukkitRunnable; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.time.LocalTime; @@ -24,13 +25,15 @@ import java.util.stream.Collectors; public class UpdateChecker extends BukkitRunnable { private final Logger logger; + private final File cacheFile; private final Set resources; static final Set availableUpdates = new HashSet<>(); static LocalTime lastChecked = null; - UpdateChecker(Logger logger, Set resources) { + UpdateChecker(Logger logger, File cacheFile, Set resources) { this.logger = logger; + this.cacheFile = cacheFile; this.resources = resources; // TODO make a copy? } @@ -79,7 +82,9 @@ public class UpdateChecker extends BukkitRunnable { public void run() { checkAll(); - try (FileOutputStream outputStream = new FileOutputStream(UpdaterManager.cacheFile)) { + DebugLogger.finer("Done checking, now saving"); + cacheFile.getParentFile().mkdirs(); + try (FileOutputStream outputStream = new FileOutputStream(cacheFile)) { VersionCheckCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet())); } catch (IOException e) { throw new RuntimeException(e); diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java similarity index 68% rename from src/main/java/eu/m724/tweaks/updater/UpdaterManager.java rename to src/main/java/eu/m724/tweaks/updater/UpdaterModule.java index b540a23..7df2351 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java @@ -7,11 +7,10 @@ package eu.m724.tweaks.updater; import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksModule; import eu.m724.tweaks.updater.cache.ResourceVersion; import eu.m724.tweaks.updater.cache.SpigotResource; import eu.m724.tweaks.updater.cache.VersionedResource; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.Plugin; import java.io.File; import java.io.FileInputStream; @@ -21,28 +20,21 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; -public class UpdaterManager { - static File cacheFile; - - private final Plugin plugin; - - public UpdaterManager(Plugin plugin) { - this.plugin = plugin; - cacheFile = new File(plugin.getDataFolder(), "storage/cache/updater"); - } - - public void init(PluginCommand updatesCommand){ +public class UpdaterModule extends TweaksModule { + @Override + protected void onInit() { // scan installed plugins - Set resources = null; + Set resources; try { - resources = new PluginScanner(plugin).load(); + resources = new PluginScanner(getPlugin()).load(); } catch (IOException e) { throw new RuntimeException("Loading plugins", e); } - cacheFile.getParentFile().mkdirs(); // TODO move this somewhere else // load installed versions from cache + var cacheFile = new File(getPlugin().getDataFolder(), "storage/cache/updater"); + Set installedVersions; try (FileInputStream inputStream = new FileInputStream(cacheFile)) { installedVersions = VersionCheckCache.loadAll(inputStream); @@ -60,9 +52,9 @@ public class UpdaterManager { )).collect(Collectors.toSet()); - new UpdateChecker(plugin.getLogger(), versionedResources) - .runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20); + new UpdateChecker(getPlugin().getLogger(), cacheFile, versionedResources) + .runTaskTimerAsynchronously(getPlugin(), 600, 12 * 3600 * 20); // 12 hours - updatesCommand.setExecutor(new UpdaterCommands()); + registerCommand("updates", new UpdaterCommands()); } } diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java similarity index 78% rename from src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java rename to src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java index 14eae1b..d4e4ecf 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java +++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java @@ -1,24 +1,25 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.worldborder; +import eu.m724.tweaks.TweaksModule; import net.minecraft.server.level.ServerLevel; import org.bukkit.craftbukkit.v1_21_R1.CraftWorld; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.plugin.Plugin; -public class WorldBorderExpander implements Listener { - public void init(Plugin plugin) { - plugin.getServer().getPluginManager().registerEvents(this, plugin); +public class WorldBorderExpandModule extends TweaksModule implements Listener { + @Override + protected void onInit() { + registerEvents(this); // because the plugin loads "post world" - plugin.getServer().getWorlds().forEach(w -> { + getPlugin().getServer().getWorlds().forEach(w -> { onWorldLoad(new WorldLoadEvent(w)); }); } diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java new file mode 100644 index 0000000..0400534 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java @@ -0,0 +1,51 @@ +/* + * 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.worldborder; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import eu.m724.tweaks.TweaksModule; + +import java.nio.ByteBuffer; + +public class WorldBorderHideModule extends TweaksModule { + private static final int EXTENSION_RADIUS = 512; + + @Override + protected void onInit() { + getPlugin().getServer().getMessenger().registerOutgoingPluginChannel(getPlugin(), "tweaks724:worldborder"); + + byte[] infoArray = ByteBuffer.allocate(4).putInt(EXTENSION_RADIUS).array(); + + onPacketSend(PacketType.Play.Server.INITIALIZE_BORDER, (event) -> { + PacketContainer packet = event.getPacket(); + // old diameter + packet.getDoubles().write(2, packet.getDoubles().read(2) + EXTENSION_RADIUS * 2); + // new diameter + packet.getDoubles().write(3, packet.getDoubles().read(3) + EXTENSION_RADIUS * 2); + + // border radius + packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS); + // warning distance + packet.getIntegers().write(1, packet.getIntegers().read(1) + EXTENSION_RADIUS); + + event.getPlayer().sendPluginMessage(getPlugin(), "tweaks724:worldborder", infoArray); + }); + + onPacketSend(PacketType.Play.Server.SET_BORDER_SIZE, (event) -> { + PacketContainer packet = event.getPacket(); + // diameter + packet.getDoubles().write(0, packet.getDoubles().read(0) + EXTENSION_RADIUS * 2); + }); + + onPacketSend(PacketType.Play.Server.SET_BORDER_WARNING_DISTANCE, (event) -> { + PacketContainer packet = event.getPacket(); + // warning distance + packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS); + }); + } +} diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java deleted file mode 100644 index 06b3491..0000000 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2024 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.worldborder; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import org.bukkit.plugin.Plugin; - -import java.nio.ByteBuffer; - -public class WorldBorderHider { - private static final int EXTENSION_RADIUS = 512; - - public void init(Plugin plugin) { - plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, "tweaks724:worldborder"); - byte[] infoArray = ByteBuffer.allocate(4).putInt(EXTENSION_RADIUS).array(); - - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Play.Server.INITIALIZE_BORDER - ) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); - // old diameter - packet.getDoubles().write(2, packet.getDoubles().read(2) + EXTENSION_RADIUS * 2); - // new diameter - packet.getDoubles().write(3, packet.getDoubles().read(3) + EXTENSION_RADIUS * 2); - - // border radius - packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS); - // warning distance - packet.getIntegers().write(1, packet.getIntegers().read(1) + EXTENSION_RADIUS); - - event.getPlayer().sendPluginMessage(plugin, "tweaks724:worldborder", infoArray); - } - }); - - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Play.Server.SET_BORDER_SIZE - ) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); - // diameter - packet.getDoubles().write(0, packet.getDoubles().read(0) + EXTENSION_RADIUS * 2); - } - }); - - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter( - plugin, - ListenerPriority.NORMAL, - PacketType.Play.Server.SET_BORDER_WARNING_DISTANCE - ) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); - // warning distance - packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS); - } - }); - } -} From a48fe97b4d412227fb18a6f561dbc5f528a157b5 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 3 Jan 2025 13:54:48 +0100 Subject: [PATCH 41/89] Elaborate on slow module Not even my fault --- .../java/eu/m724/tweaks/redstone/GatewayItem.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java index 5d24f05..4082bf3 100644 --- a/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java +++ b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java @@ -1,11 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -18,14 +19,21 @@ public class GatewayItem { private final NamespacedKey gatewayKey; public GatewayItem(Plugin plugin) { - this.gatewayKey = new NamespacedKey(plugin, "gateway"); + var start = System.nanoTime(); + this.gatewayKey = new NamespacedKey(plugin, "gateway"); var recipe = new ShapelessRecipe(gatewayKey, itemStack()); + + // this takes a long time for some reason. The first one especially + // do this somewhere off measure to JIT and skew the measurement: new RecipeChoice.MaterialChoice(Material.DIRT); recipe.addIngredient(Material.NETHER_STAR); recipe.addIngredient(Material.ENDER_CHEST); recipe.addIngredient(Material.CHORUS_FLOWER); recipe.addIngredient(Material.DAYLIGHT_DETECTOR); + plugin.getServer().addRecipe(recipe); + + DebugLogger.finer("Adding the recipe took %d ms, which is a long time", (System.nanoTime() - start) / 1000000); } public ItemStack itemStack() { From 9bcdcc17ba5afcca6fc5456915f8d329b4572d82 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 3 Jan 2025 14:12:24 +0100 Subject: [PATCH 42/89] Elaborate on warning --- .../java/eu/m724/tweaks/knockback/KnockbackModule.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java b/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java index 6b56ffb..6fe128b 100644 --- a/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java +++ b/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java @@ -49,8 +49,14 @@ public class KnockbackModule extends TweaksModule implements Listener { modifiers.put(type, new Vector(mod, mod >= 1 ? mod : 1, mod)); // don't touch vertical }); - if (!modifiers.isEmpty()) + if (!modifiers.isEmpty()) { registerEvents(this); + + try { + Class.forName("com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent"); + DebugLogger.warning("Ignore that. Server performance will NOT be affected."); + } catch (ClassNotFoundException ignored) { } + } } @EventHandler From e0d7e636a67eeefd38ae3a19bf9cd2b5a26d6478 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 3 Jan 2025 14:20:14 +0100 Subject: [PATCH 43/89] Unupdate to 1.21.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cec41b0..45ceefd 100644 --- a/pom.xml +++ b/pom.xml @@ -17,8 +17,8 @@ 21 UTF-8 - v1_21_R2 - 1.21.3 + v1_21_R1 + 1.21.1 ${project.minecraft.version}-R0.1-SNAPSHOT From 19ab653181393bbd843e29442714ac0b089e9cb8 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 5 Jan 2025 10:29:48 +0100 Subject: [PATCH 44/89] Fix config mistake --- src/main/java/eu/m724/tweaks/TweaksConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java index 4196fab..584d0fe 100644 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java @@ -142,7 +142,7 @@ public record TweaksConfig( boolean swingEnabled = config.getBoolean("swing.enabled"); TweaksConfig.config = new TweaksConfig( - debug, metrics, locale, + metrics, debug, locale, worldborderExpand, worldborderHide, brandEnabled, brandText, brandShowPing, brandShowMspt, doorDoubleOpen, doorKnocking, From 2430416915a81ac321a6b53b7ce1f746dca1c859 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 18 Jan 2025 18:36:24 +0100 Subject: [PATCH 45/89] Misc --- .forgejo/workflows/build.yml | 4 +-- README.md | 33 +++++++++---------- .../worldborder/WorldBorderExpandModule.java | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index a2ffc8e..fa8e3a7 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -7,8 +7,8 @@ jobs: - name: Install JDK and other deps run: apt update && apt install --no-install-recommends -y openjdk-21-jdk-headless maven git nodejs curl zstd - - name: Clone repository - run: git clone -b ${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} https://git.m724.eu/Minecon724/tweaks724.git . + - name: Checkout + uses: https://github.com/actions/checkout@v4 - name: Download NMS run: ./tools/download_nms.sh ~ diff --git a/README.md b/README.md index 5522659..ff77021 100644 --- a/README.md +++ b/README.md @@ -12,37 +12,37 @@ Please report all suspicious behavior. You can do so on any of those: Stuff not many other plugins do. Dependencies: -- **1.21.1**, recommended as the plugin uses NMS for some stuff \ - However, it's not forced, so it's quite probable it'll work on other versions. Please test. If you get an error, it's most often because of a module using NMS. Disable that module, and report the error \ - Why not latest? The focus is on [a widely used version](https://bstats.org/global/bukkit) that has [good mod support](https://modrinth.com/modpack/fabulously-optimized/versions?c=release) +- **1.21.1 and newer** - [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) +- To use modules marked N, you must use a JAR made precisely for your server version. # Features -### Expand world border +N - requires a specific version \ +P - requires ProtocolLib + +### Expand world border N Expands the world border to 30,000,000 (from 29,999,984) -### Hide world border +### Hide world border P Hides the world border. It's still there, just invisible. -### Server brand +### Server brand N P Modify the F3 brand, optionally include player's ping and server performance ### Doors Open two doors with one click. Knock on doors. -### MOTD +### MOTD N P Random MOTD for every ping -### Chat rooms -Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room. +### Chat mods N +- Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room. +- Proximity chat `/chat` - switch chat room \ `/chatmanage` - create, delete, modify etc. (`tweaks724.chatmanage`) -### Proximity chat -Self-explanatory - ### Compass Holding a compass shows a bar with 4 directions and stuff like beds, lodestones, death pos (TODO) etc. @@ -57,7 +57,7 @@ Updates ALL* your plugins \ `/updates` - shows available updates (`tweaks724.updates`) -### Hardcore +### Hardcore N P Hardcore hearts by chance ### Sleep @@ -78,7 +78,7 @@ It can be enabled that new players can't join the server without a key ### Full join Players with `tweaks724.bypass-full` can join even when the server is full -### Emergency alerts +### Emergency alerts P Issue messages that the player needs to read to keep playing, and that make an attention grabbing sound `/emergencyalerts` (`tweaks724.emergencyalerts`) @@ -95,12 +95,11 @@ Quickly kills (terminates) the server on trigger, via command or HTTP request. [KILLSWITCH.md for more info](/Minecon724/tweaks724/src/branch/master/docs/KILLSWITCH.md) ### Swing through grass - - +Self-explanatory ### Utility commands -- `/ping` - displays player ping \ +- `/ping` - displays player ping P \ **Ping is calculated by the plugin**. \ That allows for more precision (decimal places) and to get the ping immediately after a player join diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java index d4e4ecf..f44d781 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java +++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java @@ -34,7 +34,7 @@ public class WorldBorderExpandModule extends TweaksModule implements Listener { } level.getWorldBorder().setAbsoluteMaxSize(30000000); - // to align with player hitbox because player can't go beyond 30m - 1 and player's hitbox is 0.6 wide so we make it "hug" the border + // to align with player hitbox because player can't go beyond 30m - 1 and player's hitbox is 0.6 wide, multiply by 2 for - and +, that's 1.2 and 60000000 - 1.2 = 59999998.6 level.getWorldBorder().setSize(59999998.6); } } From e5d29388457f3baaf6a289dc0ea23fd992b730cd Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 08:10:38 +0100 Subject: [PATCH 46/89] Refactor updater --- .../eu/m724/tweaks/updater/PluginScanner.java | 59 ------------- .../m724/tweaks/updater/UpdaterCommands.java | 23 +++-- .../eu/m724/tweaks/updater/UpdaterModule.java | 86 +++++++++++++------ .../updater/{ => backend}/UpdateChecker.java | 32 ++++--- .../VersionCache.java} | 8 +- .../VersionScanner.java} | 49 +++++------ .../{cache => object}/ResourceVersion.java | 4 +- .../{cache => object}/SpigotResource.java | 7 +- .../{cache => object}/UpdateDescription.java | 7 +- .../{cache => object}/VersionedResource.java | 4 +- 10 files changed, 137 insertions(+), 142 deletions(-) delete mode 100644 src/main/java/eu/m724/tweaks/updater/PluginScanner.java rename src/main/java/eu/m724/tweaks/updater/{ => backend}/UpdateChecker.java (72%) rename src/main/java/eu/m724/tweaks/updater/{VersionCheckCache.java => backend/VersionCache.java} (94%) rename src/main/java/eu/m724/tweaks/updater/{VersionFinder.java => backend/VersionScanner.java} (74%) rename src/main/java/eu/m724/tweaks/updater/{cache => object}/ResourceVersion.java (90%) rename src/main/java/eu/m724/tweaks/updater/{cache => object}/SpigotResource.java (77%) rename src/main/java/eu/m724/tweaks/updater/{cache => object}/UpdateDescription.java (74%) rename src/main/java/eu/m724/tweaks/updater/{cache => object}/VersionedResource.java (79%) diff --git a/src/main/java/eu/m724/tweaks/updater/PluginScanner.java b/src/main/java/eu/m724/tweaks/updater/PluginScanner.java deleted file mode 100644 index a437b1c..0000000 --- a/src/main/java/eu/m724/tweaks/updater/PluginScanner.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2024 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.updater; - -import eu.m724.tweaks.updater.cache.SpigotResource; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; - -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - -public class PluginScanner { - private final Plugin thisPlugin; - - PluginScanner(Plugin thisPlugin) { - this.thisPlugin = thisPlugin; - } - - public Set load() throws IOException { - File installedPluginsYml = new File(thisPlugin.getDataFolder(), "installed_plugins.yml"); - - if (!installedPluginsYml.exists()) { - thisPlugin.saveResource("installed_plugins.yml", false); - } - - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(installedPluginsYml); - - - Plugin[] plugins = thisPlugin.getServer().getPluginManager().getPlugins(); - Set spigotResources = new HashSet<>(); - - for (Plugin plugin : plugins) { - String pluginName = plugin.getName(); - - if (!configuration.isSet(pluginName)) { - configuration.set(pluginName, -1); - continue; - } - - int pluginId = configuration.getInt(pluginName); - if (pluginId > 0) { - spigotResources.add( - new SpigotResource(plugin, pluginId, pluginName) - ); - } - } - - configuration.save(installedPluginsYml); - - return spigotResources; - - } -} diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java index 46b7c9e..a801093 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Minecon724 + * 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. */ @@ -7,7 +7,8 @@ package eu.m724.tweaks.updater; import eu.m724.tweaks.Language; -import eu.m724.tweaks.updater.cache.VersionedResource; +import eu.m724.tweaks.updater.backend.UpdateChecker; +import eu.m724.tweaks.updater.object.VersionedResource; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; @@ -20,18 +21,25 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.awt.*; +import java.time.Instant; import java.time.format.DateTimeFormatter; public class UpdaterCommands implements CommandExecutor { + private final UpdateChecker updateChecker; + + public UpdaterCommands(UpdateChecker updateChecker) { + this.updateChecker = updateChecker; + } + @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - if (UpdateChecker.lastChecked == null) { + var lastChecked = updateChecker.getLastChecked(); + if (updateChecker.getLastChecked() == -1) { sender.sendMessage(Language.getString("updatesNotChecked")); return true; } - String lastChecked = UpdateChecker.lastChecked.format(DateTimeFormatter.ofPattern("HH:mm")); - int n = UpdateChecker.availableUpdates.size(); + int n = updateChecker.getAvailableUpdates().size(); if (n > 0) { sender.spigot().sendMessage( @@ -39,13 +47,14 @@ public class UpdaterCommands implements CommandExecutor { ); int i = 0; - for (VersionedResource v : UpdateChecker.availableUpdates) { + for (VersionedResource v : updateChecker.getAvailableUpdates()) { sender.spigot().sendMessage( new ComponentBuilder(++i + ". ").color(ChatColor.GRAY).build(), resourceToBaseComponent(v) ); } } else { - sender.spigot().sendMessage(Language.getComponent("updatesNoUpdates", ChatColor.GREEN, lastChecked)); + var lastCheckedFormat = DateTimeFormatter.ofPattern("HH:mm").format(Instant.ofEpochMilli(lastChecked)); + sender.spigot().sendMessage(Language.getComponent("updatesNoUpdates", ChatColor.GREEN, lastCheckedFormat)); } return true; diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java b/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java index 7df2351..c76522c 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java +++ b/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java @@ -8,9 +8,13 @@ package eu.m724.tweaks.updater; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksModule; -import eu.m724.tweaks.updater.cache.ResourceVersion; -import eu.m724.tweaks.updater.cache.SpigotResource; -import eu.m724.tweaks.updater.cache.VersionedResource; +import eu.m724.tweaks.updater.backend.UpdateChecker; +import eu.m724.tweaks.updater.backend.VersionCache; +import eu.m724.tweaks.updater.object.ResourceVersion; +import eu.m724.tweaks.updater.object.SpigotResource; +import eu.m724.tweaks.updater.object.VersionedResource; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; import java.io.File; import java.io.FileInputStream; @@ -23,38 +27,72 @@ import java.util.stream.Collectors; public class UpdaterModule extends TweaksModule { @Override protected void onInit() { - // scan installed plugins - Set resources; - try { - resources = new PluginScanner(getPlugin()).load(); - } catch (IOException e) { - throw new RuntimeException("Loading plugins", e); - } - + var resources = loadInstalledPlugins(); // load installed versions from cache var cacheFile = new File(getPlugin().getDataFolder(), "storage/cache/updater"); - Set installedVersions; + final var installedVersions = loadInstalledVersionCache(cacheFile); + + var versionedResources = resources.stream() + .map(res -> new VersionedResource( + res, installedVersions.stream().filter(iv -> iv.resourceId() == res.resourceId()).findFirst().orElse(null), null + )) + .collect(Collectors.toSet()); + + + var updateChecker = new UpdateChecker(getPlugin().getLogger(), cacheFile, versionedResources); + updateChecker.runTaskTimerAsynchronously(getPlugin(), 600, 12 * 3600 * 20); // 12 hours + + registerCommand("updates", new UpdaterCommands(updateChecker)); + } + + private Set loadInstalledVersionCache(File cacheFile) { try (FileInputStream inputStream = new FileInputStream(cacheFile)) { - installedVersions = VersionCheckCache.loadAll(inputStream); - } catch (FileNotFoundException e) { - installedVersions = new HashSet<>(); + return VersionCache.loadAll(inputStream); + } catch (FileNotFoundException ignored) { } catch (IOException e) { DebugLogger.warning("Error loading installed version cache, starting fresh. " + e.getMessage()); - installedVersions = new HashSet<>(); } - final Set ivf = installedVersions; - Set versionedResources = resources.stream() - .map(res -> new VersionedResource( - res, ivf.stream().filter(iv -> iv.resourceId() == res.resourceId()).findFirst().orElse(null), null - )).collect(Collectors.toSet()); + return new HashSet<>(); + } + private Set loadInstalledPlugins() { + File installedPluginsYml = new File(getPlugin().getDataFolder(), "installed_plugins.yml"); - new UpdateChecker(getPlugin().getLogger(), cacheFile, versionedResources) - .runTaskTimerAsynchronously(getPlugin(), 600, 12 * 3600 * 20); // 12 hours + if (!installedPluginsYml.exists()) { + getPlugin().saveResource("installed_plugins.yml", false); + } + + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(installedPluginsYml); + + Plugin[] plugins = getPlugin().getServer().getPluginManager().getPlugins(); + Set spigotResources = new HashSet<>(); + + for (Plugin plugin : plugins) { + String pluginName = plugin.getName(); + + if (!configuration.isSet(pluginName)) { + configuration.set(pluginName, -1); + continue; + } + + int pluginId = configuration.getInt(pluginName); + if (pluginId > 0) { + spigotResources.add( + new SpigotResource(plugin, pluginId, pluginName) + ); + } + } + + try { + configuration.save(installedPluginsYml); + } catch (IOException e) { + throw new RuntimeException("Failed to update installed_plugins.yml", e); + } + + return spigotResources; - registerCommand("updates", new UpdaterCommands()); } } diff --git a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java similarity index 72% rename from src/main/java/eu/m724/tweaks/updater/UpdateChecker.java rename to src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java index 2f4d4d5..72f3ac6 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java @@ -4,18 +4,16 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater; +package eu.m724.tweaks.updater.backend; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; -import eu.m724.tweaks.updater.cache.VersionedResource; +import eu.m724.tweaks.updater.object.VersionedResource; import org.bukkit.scheduler.BukkitRunnable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.time.LocalTime; -import java.time.ZoneOffset; import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -28,10 +26,10 @@ public class UpdateChecker extends BukkitRunnable { private final File cacheFile; private final Set resources; - static final Set availableUpdates = new HashSet<>(); - static LocalTime lastChecked = null; + private final Set availableUpdates = new HashSet<>(); + private long lastChecked = -1; - UpdateChecker(Logger logger, File cacheFile, Set resources) { + public UpdateChecker(Logger logger, File cacheFile, Set resources) { this.logger = logger; this.cacheFile = cacheFile; this.resources = resources; // TODO make a copy? @@ -39,7 +37,7 @@ public class UpdateChecker extends BukkitRunnable { private void checkAll() { DebugLogger.fine("Checking for updates"); - lastChecked = LocalTime.now(ZoneOffset.UTC); + lastChecked = System.currentTimeMillis(); availableUpdates.clear(); for (VersionedResource versionedResource : Set.copyOf(resources)) { @@ -47,19 +45,21 @@ public class UpdateChecker extends BukkitRunnable { int page = versionedResource.running() != null ? versionedResource.running().page() : 1; try { - VersionedResource newResource = new VersionFinder(versionedResource.resource(), page).join(); // this runs async so it's ok + VersionedResource newResource = new VersionScanner(versionedResource.resource(), page).join(); // this runs async so it's ok if (!versionedResource.equals(newResource)) { resources.remove(versionedResource); + if (newResource.running() == null) { - logger.warning("Unable to find installed version of %s".formatted(pluginName)); + DebugLogger.warning("Unable to find installed version of %s", pluginName); if (versionedResource.running() != null) { - logger.warning("Did you downgrade %s? If so, clear cache".formatted(pluginName)); + DebugLogger.warning("Did you downgrade %s? If so, clear cache", pluginName); } } else { if (!newResource.running().equals(newResource.latest())) { availableUpdates.add(newResource); } } + resources.add(newResource); } } catch (CompletionException e) { @@ -85,11 +85,19 @@ public class UpdateChecker extends BukkitRunnable { DebugLogger.finer("Done checking, now saving"); cacheFile.getParentFile().mkdirs(); try (FileOutputStream outputStream = new FileOutputStream(cacheFile)) { - VersionCheckCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet())); + VersionCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet())); } catch (IOException e) { throw new RuntimeException(e); } alert(); } + + public long getLastChecked() { + return lastChecked; + } + + public Set getAvailableUpdates() { + return availableUpdates; + } } diff --git a/src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java b/src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java similarity index 94% rename from src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java rename to src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java index 7bc9b44..a2f0797 100644 --- a/src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java +++ b/src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java @@ -1,12 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater; +package eu.m724.tweaks.updater.backend; -import eu.m724.tweaks.updater.cache.ResourceVersion; +import eu.m724.tweaks.updater.object.ResourceVersion; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -15,7 +15,7 @@ import java.io.OutputStream; import java.util.HashSet; import java.util.Set; -public class VersionCheckCache { +public class VersionCache { private static final byte FILE_VERSION = 1; public static Set loadAll(FileInputStream inputStream) throws IOException { diff --git a/src/main/java/eu/m724/tweaks/updater/VersionFinder.java b/src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java similarity index 74% rename from src/main/java/eu/m724/tweaks/updater/VersionFinder.java rename to src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java index 35676ef..6cd6262 100644 --- a/src/main/java/eu/m724/tweaks/updater/VersionFinder.java +++ b/src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java @@ -1,19 +1,20 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater; +package eu.m724.tweaks.updater.backend; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import eu.m724.tweaks.updater.cache.SpigotResource; -import eu.m724.tweaks.updater.cache.ResourceVersion; -import eu.m724.tweaks.updater.cache.UpdateDescription; -import eu.m724.tweaks.updater.cache.VersionedResource; +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.updater.object.SpigotResource; +import eu.m724.tweaks.updater.object.ResourceVersion; +import eu.m724.tweaks.updater.object.UpdateDescription; +import eu.m724.tweaks.updater.object.VersionedResource; import java.net.URI; import java.net.URISyntaxException; @@ -26,23 +27,25 @@ import java.util.concurrent.Executors; // TODO optimize -public class VersionFinder extends CompletableFuture { +public class VersionScanner extends CompletableFuture { private final SpigotResource resource; private final int fromPage; - VersionFinder(SpigotResource resource, int fromPage) { + VersionScanner(SpigotResource resource, int fromPage) { this.resource = resource; this.fromPage = fromPage; start(); } - VersionFinder(SpigotResource resource) { + VersionScanner(SpigotResource resource) { this(resource, 1); } private void start() { //System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName()); + DebugLogger.finer("Scanning %s (#%d) from page %d", resource.name(), resource.resourceId(), fromPage); + try (ExecutorService executor = Executors.newSingleThreadExecutor()) { executor.execute(() -> { try { @@ -51,13 +54,14 @@ public class VersionFinder extends CompletableFuture { int page; for (page = fromPage; page < 1000; page++) { - //System.out.println("Page " + page); + DebugLogger.finer("Scan %s now at page %d", resource.name(), fromPage); + String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId()); HttpRequest request; try { request = HttpRequest.newBuilder(new URI(url)) - .header("User-Agent", "twu/1") + .header("User-Agent", "twu/1") // tweaks updater v1 .build(); } catch (URISyntaxException e) { throw new RuntimeException(e); @@ -68,6 +72,7 @@ public class VersionFinder extends CompletableFuture { String body = response.body(); if (body.isBlank()) { + DebugLogger.finer("Body is blank, stopping"); page--; break; } @@ -75,15 +80,7 @@ public class VersionFinder extends CompletableFuture { JsonArray jsonArray = JsonParser.parseString(body).getAsJsonArray(); for (JsonElement ele : jsonArray) { JsonObject versionJson = ele.getAsJsonObject(); - if (isRunningVersion(versionJson)) { - runningVersion = new ResourceVersion( - resource.resourceId(), - page, - versionJson.get("id").getAsInt(), - versionJson.get("resource_version").getAsString(), - null // no need for changelog of running version - ); - } + latestVersion = new ResourceVersion( resource.resourceId(), page, @@ -94,14 +91,17 @@ public class VersionFinder extends CompletableFuture { versionJson.get("message").getAsString() ) ); - //System.out.printf("%d %d %s\n", page, versionJson.get("id").getAsInt(), versionJson.get("resource_version").getAsString()); + + if (isRunningVersion(versionJson)) + runningVersion = latestVersion; + + DebugLogger.finer("%s - %s #%d", resource.name(), latestVersion.updateId(), latestVersion.updateId()); } if (jsonArray.size() < 10) break; } } - //System.out.println("Done"); if (page > 999) { throw new Exception("Too many pages"); @@ -117,7 +117,8 @@ public class VersionFinder extends CompletableFuture { } private boolean isRunningVersion(JsonObject versionJson) { - // TODO - return versionJson.get("resource_version").getAsString().equals(resource.plugin().getDescription().getVersion()); + // TODO make it work with more advanced strings + return versionJson.get("resource_version").getAsString() + .equals(resource.plugin().getDescription().getVersion()); } } diff --git a/src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java b/src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java similarity index 90% rename from src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java rename to src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java index d5d0fd3..6bebcea 100644 --- a/src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java +++ b/src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater.cache; +package eu.m724.tweaks.updater.object; import java.util.Objects; diff --git a/src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java b/src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java similarity index 77% rename from src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java rename to src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java index dce97cf..c2c7a8a 100644 --- a/src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java +++ b/src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater.cache; +package eu.m724.tweaks.updater.object; import org.bukkit.plugin.Plugin; @@ -12,5 +12,4 @@ public record SpigotResource( Plugin plugin, int resourceId, String name -) { -} +) { } diff --git a/src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java b/src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java similarity index 74% rename from src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java rename to src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java index 1837716..508b8bd 100644 --- a/src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java +++ b/src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java @@ -1,13 +1,12 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater.cache; +package eu.m724.tweaks.updater.object; public record UpdateDescription( String title, String description -) { -} +) { } diff --git a/src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java b/src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java similarity index 79% rename from src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java rename to src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java index 18d4bb2..f140bb9 100644 --- a/src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java +++ b/src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.updater.cache; +package eu.m724.tweaks.updater.object; public record VersionedResource( SpigotResource resource, From 0c044febd555ea4d1867e158673bb4e41637ea19 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 08:10:59 +0100 Subject: [PATCH 47/89] Clarify updater in README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ff77021..7a344bd 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ Self-discipline with a pomodoro timer that's actually forced `/pomodoro` (`tweaks724.pomodoro`) ### Updater -Updates ALL* your plugins \ +Checks for updates of ALL* your plugins \ +Updates are still installed manually \ *Those on SpigotMC and that release updates there `/updates` - shows available updates (`tweaks724.updates`) From f891fbbb905c0786a3821229394df6fd6ec4e2fa Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 10:36:50 +0100 Subject: [PATCH 48/89] Make 1.21.4 the native version --- pom.xml | 8 ++++---- src/main/java/eu/m724/tweaks/chat/ChatListener.java | 4 ++-- .../m724/tweaks/worldborder/WorldBorderExpandModule.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 45ceefd..edf4335 100644 --- a/pom.xml +++ b/pom.xml @@ -17,8 +17,8 @@ 21 UTF-8 - v1_21_R1 - 1.21.1 + v1_21_R3 + 1.21.4 ${project.minecraft.version}-R0.1-SNAPSHOT @@ -44,7 +44,7 @@ - + @@ -58,7 +58,7 @@ - + diff --git a/src/main/java/eu/m724/tweaks/chat/ChatListener.java b/src/main/java/eu/m724/tweaks/chat/ChatListener.java index 83dc4c2..b94d770 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatListener.java +++ b/src/main/java/eu/m724/tweaks/chat/ChatListener.java @@ -14,8 +14,8 @@ import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TranslatableComponent; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.chat.Component; -import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry; -import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_21_R3.CraftRegistry; +import org.bukkit.craftbukkit.v1_21_R3.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java index f44d781..2f735ad 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java +++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java @@ -8,7 +8,7 @@ package eu.m724.tweaks.worldborder; import eu.m724.tweaks.TweaksModule; import net.minecraft.server.level.ServerLevel; -import org.bukkit.craftbukkit.v1_21_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_21_R3.CraftWorld; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.WorldLoadEvent; From b9b0484d243f555552b658b123c32fd40701cbec Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:02:18 +0100 Subject: [PATCH 49/89] Add building guide --- .mvn/wrapper/maven-wrapper.properties | 19 ++ docs/BUILDING.md | 25 +++ docs/DEVELOPMENT.md | 5 - mvnw | 259 ++++++++++++++++++++++++++ mvnw.cmd | 149 +++++++++++++++ pom.xml | 6 +- 6 files changed, 455 insertions(+), 8 deletions(-) create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 docs/BUILDING.md delete mode 100644 docs/DEVELOPMENT.md create mode 100755 mvnw create mode 100644 mvnw.cmd diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/docs/BUILDING.md b/docs/BUILDING.md new file mode 100644 index 0000000..91fecbf --- /dev/null +++ b/docs/BUILDING.md @@ -0,0 +1,25 @@ +1. Download BuildTools, move it into an empty directory and open terminal +2. Download Minecraft sources: + ``` + java -jar BuildTools.jar --rev 1.21.4 --remapped + ``` + +3. Clone this repository: + ``` + git clone https://git.m724.eu/Minecon724/tweaks724 + cd tweaks724 + ``` + - You might want to `checkout` a release: + ``` + git checkout tags/tweaks-0.1.12 + ``` +4. To compile for native version: + ``` + ./mvnw package + ``` + To compile for another version: + ``` + ./mvnw package -Dproject.craftbukkit.version=v1_21_R3 -Dproject.minecraft.version=1.21.4 + ``` + +5. Look for `tweaks-0.1.12+1.21.4.jar` in `target/` \ No newline at end of file diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md deleted file mode 100644 index e1404cb..0000000 --- a/docs/DEVELOPMENT.md +++ /dev/null @@ -1,5 +0,0 @@ -To setup NMS: -1. Download BuildTools, move it into an empty directory and open terminal -2. ``` - java -jar BuildTools.jar --rev 1.21.1 --remapped - ``` \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index edf4335..7bd6472 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 21 UTF-8 - v1_21_R3 + v1_21_R3 1.21.4 ${project.minecraft.version}-R0.1-SNAPSHOT @@ -44,7 +44,7 @@ - + @@ -58,7 +58,7 @@ - + From 6e0d7e5a40c7f2ff5e21a93d0f05f6c09f681bdd Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:16:01 +0100 Subject: [PATCH 50/89] Fix sleep --- .../java/eu/m724/tweaks/sleep/SleepListener.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java index 8aa5579..129a02b 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java +++ b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java @@ -8,7 +8,7 @@ package eu.m724.tweaks.sleep; import eu.m724.tweaks.TweaksConfig; import org.bukkit.GameRule; -import org.bukkit.World; +import org.bukkit.attribute.Attribute; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -31,20 +31,21 @@ public class SleepListener implements Listener { if (event.getBedEnterResult() == PlayerBedEnterEvent.BedEnterResult.OK) { SleepState.playersSleeping++; - World world = event.getPlayer().getWorld(); + var player = event.getPlayer(); + var world = player.getWorld(); long day = world.getFullTime() / 24000; if (day != lastDay) skippedCurrentNight.clear(); lastDay = day; - if (!skippedCurrentNight.contains(event.getPlayer())) { + if (skippedCurrentNight.add(player)) { if (instant) { - double onePlayerRatio = 1 / (event.getPlayer().getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0)); + double onePlayerRatio = 1 / (player.getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0)); world.setTime(Math.min(world.getTime() + (long) (10917 * onePlayerRatio), 23459)); - skippedCurrentNight.add(event.getPlayer()); } - event.getPlayer().setHealth(event.getPlayer().getHealth() + heal); + var maxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue(); + player.setHealth(Math.min(player.getHealth() + heal, maxHealth)); } } From 832a5edcccc7e33332d8cc52c70e17c300b66d44 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:16:20 +0100 Subject: [PATCH 51/89] Add version notice --- .../java/eu/m724/tweaks/TweaksPlugin.java | 26 +++++++++++++++++++ src/main/resources/plugin.yml | 3 +++ 2 files changed, 29 insertions(+) diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 42975fc..e427283 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -58,6 +58,23 @@ public class TweaksPlugin extends MStatsPlugin { new Language(Locale.of(config.locale())); // TODO DebugLogger.fine(Language.getString("languageNotice", Language.getString("language"), Language.getString("languageEnglish"))); + var runningVersion = getServer().getBukkitVersion(); + var targetVersion = getTargetVersion(); + + if (!runningVersion.equals(targetVersion)) { + // the incompatibility can be between 1.21.4-R0.1-SNAPSHOT and 1.21.4-R1-SNAPSHOT + var runningMc = runningVersion.split("-")[0]; + var targetMc = targetVersion.split("-")[0]; + if (!runningMc.equals(targetMc)) { + targetVersion = targetMc; + runningVersion = runningMc; + } + + getLogger().warning("This plugin was built for %s. This server is running %s.".formatted(targetVersion, runningVersion)); + getLogger().warning("Some modules will not work. Disable those modules, or make a compatible build yourself:"); + getLogger().warning("https://git.m724.eu/Minecon724/tweaks724/src/branch/master/docs/BUILDING.md"); + } + /* start modules */ if (config.worldborderHide()) { @@ -141,6 +158,15 @@ public class TweaksPlugin extends MStatsPlugin { DebugLogger.fine("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); } + private String getTargetVersion() { + var permission = getServer().getPluginManager().getPermission("7weaks724.ignore.this"); + + var desc = permission.getDescription().substring("Internal, not for use. ".length()).split(","); + var version = desc[0]; + + return version; + } + public boolean hasResource(String resource) { return this.getClassLoader().getResource(resource) != null; } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fac4b46..7882556 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -42,6 +42,9 @@ commands: permission: tweaks724.servkill permissions: + 7weaks724.ignore.this: + description: "Internal, not for use. ${project.spigot.version}" + default: false tweaks724: chatmanage: default: true From 35ddd0563cad98fd120a1bcb5e39cee690c5f2d2 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:21:27 +0100 Subject: [PATCH 52/89] Remove unused deps --- pom.xml | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/pom.xml b/pom.xml index 7bd6472..abdd61e 100644 --- a/pom.xml +++ b/pom.xml @@ -67,37 +67,6 @@ - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - false - true - - - eu.m724:tweaks - - - - - * - - META-INF/** - - - - - - - package - - shade - - - - - net.md-5 specialsource-maven-plugin @@ -152,11 +121,6 @@ dmulloy2-repo https://repo.dmulloy2.net/repository/public/ - - - maxhenkel-repo - https://maven.maxhenkel.de/repository/public - m724-repo https://git.m724.eu/api/packages/Minecon724/maven @@ -183,12 +147,6 @@ 5.3.0 provided - - de.maxhenkel.voicechat - voicechat-api - 2.5.0 - provided - eu.m724 mstats-spigot From 174d0ae10c44f862f0c13efe393e8bc0e7009e9e Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:21:56 +0100 Subject: [PATCH 53/89] [maven-release-plugin] prepare release tweaks-0.1.12 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index abdd61e..ad61708 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.12-SNAPSHOT + 0.1.12 21 @@ -171,6 +171,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.12 \ No newline at end of file From f43b17078ef659d93b82fb9c66f1821c270ff2bc Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 11:21:57 +0100 Subject: [PATCH 54/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ad61708..9d20389 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.12 + 0.1.13-SNAPSHOT 21 @@ -171,6 +171,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.12 + HEAD \ No newline at end of file From 2890f00acd24fe8e2e23d77b787c1ea489b9ee4c Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 12:12:12 +0100 Subject: [PATCH 55/89] Improve build guide --- README.md | 2 +- docs/BUILDING.md | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7a344bd..f748457 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Stuff not many other plugins do. Dependencies: - **1.21.1 and newer** - [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) -- To use modules marked N, you must use a JAR made precisely for your server version. +- To use modules marked N, you must use a JAR [made for the exact server version.](/Minecon724/tweaks724/src/branch/master/docs/BUILDING.md) # Features diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 91fecbf..7af000f 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,10 +1,17 @@ -1. Download BuildTools, move it into an empty directory and open terminal -2. Download Minecraft sources: - ``` - java -jar BuildTools.jar --rev 1.21.4 --remapped - ``` +First, download NMS. There are two ways: -3. Clone this repository: +- Use `tools/download_nms.sh` +- Download BuildTools, move it into an empty directory and run: + ``` + java -jar BuildTools.jar --rev 1.21.4 --remapped + ``` + You must run this for every version you want to build for. + + + +Then build the plugin: + +1. Clone this repository: ``` git clone https://git.m724.eu/Minecon724/tweaks724 cd tweaks724 @@ -13,13 +20,13 @@ ``` git checkout tags/tweaks-0.1.12 ``` -4. To compile for native version: +2. For the "native" version: ``` ./mvnw package ``` - To compile for another version: + For another compatible version: ``` ./mvnw package -Dproject.craftbukkit.version=v1_21_R3 -Dproject.minecraft.version=1.21.4 ``` -5. Look for `tweaks-0.1.12+1.21.4.jar` in `target/` \ No newline at end of file +Look for `tweaks-0.1.12+1.21.4.jar` in `target/` \ No newline at end of file From bcd6827c292742c7172d8ed24d7c7b69e1c5e7b5 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 12:12:42 +0100 Subject: [PATCH 56/89] Fix workflow and make it on Alpine --- .forgejo/workflows/build.yml | 19 +++++++++---------- pom.xml | 5 +---- tools/download_nms.sh | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index fa8e3a7..5afcc3c 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -2,10 +2,10 @@ on: [push] jobs: build: runs-on: docker - container: debian:sid + container: eclipse-temurin:21-alpine steps: - - name: Install JDK and other deps - run: apt update && apt install --no-install-recommends -y openjdk-21-jdk-headless maven git nodejs curl zstd + - name: Install build dependencies + run: apk add nodejs curl tar zstd - name: Checkout uses: https://github.com/actions/checkout@v4 @@ -14,19 +14,18 @@ jobs: run: ./tools/download_nms.sh ~ - - - name: Build for 1.21.1 - run: mvn package -Dproject.minecraft.version=1.21.1 -Dproject.nms.version=v1_21_R1 + - name: Build for 1.21.4 + run: ./mvnw package -Dproject.minecraft.version=1.21.4 -Dproject.craftbukkit.version=v1_21_R3 - name: Build for 1.21.3 - run: mvn package -Dproject.minecraft.version=1.21.3 -Dproject.nms.version=v1_21_R2 + run: ./mvnw package -Dproject.minecraft.version=1.21.3 -Dproject.craftbukkit.version=v1_21_R2 - - name: Build for 1.21.4 - run: mvn package -Dproject.minecraft.version=1.21.4 -Dproject.nms.version=v1_21_R3 + - name: Build for 1.21.1 + run: ./mvnw package -Dproject.minecraft.version=1.21.1 -Dproject.craftbukkit.version=v1_21_R1 - name: Upload artifacts uses: https://github.com/actions/upload-artifact@v3 with: - path: target \ No newline at end of file + path: target/tweaks-*.jar \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9d20389..cce77e1 100644 --- a/pom.xml +++ b/pom.xml @@ -80,10 +80,8 @@ remap-obf org.spigotmc:minecraft-server:${project.spigot.version}:txt:maps-mojang - true org.spigotmc:spigot:${project.spigot.version}:jar:remapped-mojang - true - remapped-obf-temp-dont-use + true @@ -93,7 +91,6 @@ remap-spigot - ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf-temp-dont-use.jar org.spigotmc:minecraft-server:${project.spigot.version}:csrg:maps-spigot org.spigotmc:spigot:${project.spigot.version}:jar:remapped-obf diff --git a/tools/download_nms.sh b/tools/download_nms.sh index c22aac4..95a44be 100755 --- a/tools/download_nms.sh +++ b/tools/download_nms.sh @@ -1,7 +1,7 @@ -#!/bin/bash +#!/bin/sh # -# Copyright (C) 2024 Minecon724 +# 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. # From 7ed9a702ca18821002eae06e291537787f982828 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 12:49:37 +0100 Subject: [PATCH 57/89] Replace nonsensical text --- src/main/resources/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index dd439da..30aa5a2 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -81,8 +81,7 @@ hardcore: # 0.0 - 1.0 decimal. This is if you want to make it like an Easter egg chance: 1.0 -# Makes sleeping -# And adds a nice animation +# Sleep tweaks # Percentage: playersSleepingPercentage gamerule # If instant: how much % of players to skip the night # If not: how much % make skipping full speed From 15c97ee256e3fd630062202c6719890e923da0a9 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 12:50:54 +0100 Subject: [PATCH 58/89] Ask to keep metrics --- src/main/resources/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 30aa5a2..5083716 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -5,7 +5,7 @@ # - https://discord.gg/86X4Z5JUeq # - https://www.spigotmc.org/threads/tweaks724.670906/ -# Metrics toggle. Ideally opt-in, but the system is very new and it needs testing. +# Metrics toggle. Please keep this on. metrics: true # Warning: Don't use /worldborder while this is on From 1ac32a093f906773de746e3990cb260c17d993e2 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 13:54:19 +0100 Subject: [PATCH 59/89] Use boring syntax for permissions --- src/main/resources/plugin.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7882556..5b193b2 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -42,23 +42,23 @@ commands: permission: tweaks724.servkill permissions: + tweaks724.chatmanage: + default: true + tweaks724.pomodoro: + default: true + tweaks724.updates: + default: op + tweaks724.tauth: + default: op + tweaks724.bypass-full: + default: op + tweaks724.emergencyalert: + default: op + tweaks724.retstone: + default: op + tweaks724.servkill: + default: false + 7weaks724.ignore.this: description: "Internal, not for use. ${project.spigot.version}" default: false - tweaks724: - chatmanage: - default: true - pomodoro: - default: true - updates: - default: op - tauth: - default: op - bypass-full: - default: op - emergencyalert: - default: op - retstone: - default: op - servkill: - default: false From cbfbdf8ce3f045896bdb50c3ed600ca8ada49db3 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 13:54:41 +0100 Subject: [PATCH 60/89] [maven-release-plugin] prepare release tweaks-0.1.13 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cce77e1..ca2eb2e 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.13-SNAPSHOT + 0.1.13 21 @@ -168,6 +168,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.13 \ No newline at end of file From 27888299679f24c9c10a4a44ea48d03c0a8cc060 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 20 Jan 2025 13:54:42 +0100 Subject: [PATCH 61/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ca2eb2e..9663441 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.13 + 0.1.14-SNAPSHOT 21 @@ -168,6 +168,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.13 + HEAD \ No newline at end of file From 7b65be86ad3be42991a3c5ba005ee408105d1491 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 24 Jan 2025 10:05:49 +0100 Subject: [PATCH 62/89] Move modules to modules --- src/main/java/eu/m724/tweaks/DebugLogger.java | 2 + .../java/eu/m724/tweaks/TweaksPlugin.java | 39 ++++++++++--------- .../tweaks/{ => module}/TweaksModule.java | 5 ++- .../m724/tweaks/{ => module}/alert/Alert.java | 4 +- .../{ => module}/alert/AlertCommand.java | 2 +- .../{ => module}/alert/AlertModule.java | 4 +- .../{ => module}/alert/AlertRunnable.java | 4 +- .../{ => module}/auth/AuthCommands.java | 4 +- .../{ => module}/auth/AuthListener.java | 4 +- .../tweaks/{ => module}/auth/AuthModule.java | 4 +- .../tweaks/{ => module}/auth/AuthStorage.java | 4 +- .../{ => module}/chat/ChatCommands.java | 2 +- .../{ => module}/chat/ChatFormatUtils.java | 4 +- .../{ => module}/chat/ChatListener.java | 2 +- .../tweaks/{ => module}/chat/ChatModule.java | 4 +- .../tweaks/{ => module}/chat/ChatRoom.java | 4 +- .../{ => module}/chat/ChatRoomLoader.java | 4 +- .../{ => module}/compass/CompassModule.java | 4 +- .../compass/CompassPlayerPreferences.java | 4 +- .../{ => module}/door/DoorKnockModule.java | 4 +- .../{ => module}/door/DoorOpenModule.java | 4 +- .../tweaks/{ => module}/full/FullModule.java | 4 +- .../{ => module}/hardcore/HardcoreModule.java | 4 +- .../killswitch/KillswitchModule.java | 4 +- .../{ => module}/killswitch/Ratelimit.java | 2 +- .../knockback/KnockbackModule.java | 4 +- .../tweaks/{ => module}/motd/MotdModule.java | 4 +- .../{ => module}/ping/F3NameListener.java | 4 +- .../ping/KeepAlivePingChecker.java | 4 +- .../tweaks/{ => module}/ping/MsptChecker.java | 4 +- .../tweaks/{ => module}/ping/PingChecker.java | 2 +- .../{ => module}/ping/PingCommands.java | 4 +- .../{ => module}/ping/PlayerPingStorage.java | 4 +- .../{ => module}/pomodoro/PlayerPomodoro.java | 4 +- .../pomodoro/PomodoroCommands.java | 4 +- .../pomodoro/PomodoroListener.java | 4 +- .../{ => module}/pomodoro/PomodoroModule.java | 4 +- .../pomodoro/PomodoroRunnable.java | 4 +- .../{ => module}/pomodoro/Pomodoros.java | 4 +- .../{ => module}/redstone/GatewayItem.java | 2 +- .../redstone/RedstoneCommands.java | 4 +- .../redstone/RedstoneGateways.java | 4 +- .../redstone/RedstoneListener.java | 4 +- .../{ => module}/redstone/RedstoneModule.java | 4 +- .../redstone/RedstoneStateUpdateRunnable.java | 4 +- .../{ => module}/redstone/RedstoneStore.java | 4 +- .../{ => module}/sleep/SleepListener.java | 2 +- .../{ => module}/sleep/SleepModule.java | 4 +- .../tweaks/{ => module}/sleep/SleepState.java | 4 +- .../sleep/TimeForwardRunnable.java | 4 +- .../{ => module}/swing/SwingModule.java | 4 +- .../{ => module}/updater/UpdaterCommands.java | 6 +-- .../{ => module}/updater/UpdaterModule.java | 14 +++---- .../updater/backend/UpdateChecker.java | 4 +- .../updater/backend/VersionCache.java | 4 +- .../updater/backend/VersionScanner.java | 10 ++--- .../updater/object/ResourceVersion.java | 2 +- .../updater/object/SpigotResource.java | 2 +- .../updater/object/UpdateDescription.java | 2 +- .../updater/object/VersionedResource.java | 2 +- .../worldborder/WorldBorderExpandModule.java | 4 +- .../worldborder/WorldBorderHideModule.java | 4 +- 62 files changed, 142 insertions(+), 136 deletions(-) rename src/main/java/eu/m724/tweaks/{ => module}/TweaksModule.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/alert/Alert.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/alert/AlertCommand.java (99%) rename src/main/java/eu/m724/tweaks/{ => module}/alert/AlertModule.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/alert/AlertRunnable.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/auth/AuthCommands.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/auth/AuthListener.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/auth/AuthModule.java (85%) rename src/main/java/eu/m724/tweaks/{ => module}/auth/AuthStorage.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatCommands.java (99%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatFormatUtils.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatListener.java (99%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatModule.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatRoom.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/chat/ChatRoomLoader.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/compass/CompassModule.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/compass/CompassPlayerPreferences.java (89%) rename src/main/java/eu/m724/tweaks/{ => module}/door/DoorKnockModule.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/door/DoorOpenModule.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/full/FullModule.java (89%) rename src/main/java/eu/m724/tweaks/{ => module}/hardcore/HardcoreModule.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/killswitch/KillswitchModule.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/killswitch/Ratelimit.java (93%) rename src/main/java/eu/m724/tweaks/{ => module}/knockback/KnockbackModule.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/motd/MotdModule.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/F3NameListener.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/KeepAlivePingChecker.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/MsptChecker.java (89%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/PingChecker.java (94%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/PingCommands.java (94%) rename src/main/java/eu/m724/tweaks/{ => module}/ping/PlayerPingStorage.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/PlayerPomodoro.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/PomodoroCommands.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/PomodoroListener.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/PomodoroModule.java (85%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/PomodoroRunnable.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/pomodoro/Pomodoros.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/GatewayItem.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneCommands.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneGateways.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneListener.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneModule.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneStateUpdateRunnable.java (94%) rename src/main/java/eu/m724/tweaks/{ => module}/redstone/RedstoneStore.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/sleep/SleepListener.java (98%) rename src/main/java/eu/m724/tweaks/{ => module}/sleep/SleepModule.java (85%) rename src/main/java/eu/m724/tweaks/{ => module}/sleep/SleepState.java (74%) rename src/main/java/eu/m724/tweaks/{ => module}/sleep/TimeForwardRunnable.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/swing/SwingModule.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/UpdaterCommands.java (95%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/UpdaterModule.java (89%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/backend/UpdateChecker.java (97%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/backend/VersionCache.java (96%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/backend/VersionScanner.java (94%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/object/ResourceVersion.java (93%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/object/SpigotResource.java (87%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/object/UpdateDescription.java (85%) rename src/main/java/eu/m724/tweaks/{ => module}/updater/object/VersionedResource.java (87%) rename src/main/java/eu/m724/tweaks/{ => module}/worldborder/WorldBorderExpandModule.java (93%) rename src/main/java/eu/m724/tweaks/{ => module}/worldborder/WorldBorderHideModule.java (95%) diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java index d74b63c..9bf66c6 100644 --- a/src/main/java/eu/m724/tweaks/DebugLogger.java +++ b/src/main/java/eu/m724/tweaks/DebugLogger.java @@ -6,6 +6,8 @@ package eu.m724.tweaks; +import eu.m724.tweaks.module.TweaksModule; + import java.util.logging.Level; import java.util.logging.Logger; diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index e427283..1f25ca3 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -7,25 +7,26 @@ package eu.m724.tweaks; import eu.m724.mstats.MStatsPlugin; -import eu.m724.tweaks.alert.AlertModule; -import eu.m724.tweaks.auth.AuthModule; -import eu.m724.tweaks.chat.ChatModule; -import eu.m724.tweaks.door.DoorKnockModule; -import eu.m724.tweaks.door.DoorOpenModule; -import eu.m724.tweaks.full.FullModule; -import eu.m724.tweaks.hardcore.HardcoreModule; -import eu.m724.tweaks.killswitch.KillswitchModule; -import eu.m724.tweaks.knockback.KnockbackModule; -import eu.m724.tweaks.motd.MotdModule; -import eu.m724.tweaks.ping.F3NameListener; -import eu.m724.tweaks.ping.PingChecker; -import eu.m724.tweaks.pomodoro.PomodoroModule; -import eu.m724.tweaks.redstone.RedstoneModule; -import eu.m724.tweaks.sleep.SleepModule; -import eu.m724.tweaks.swing.SwingModule; -import eu.m724.tweaks.updater.UpdaterModule; -import eu.m724.tweaks.worldborder.WorldBorderExpandModule; -import eu.m724.tweaks.worldborder.WorldBorderHideModule; +import eu.m724.tweaks.module.TweaksModule; +import eu.m724.tweaks.module.alert.AlertModule; +import eu.m724.tweaks.module.auth.AuthModule; +import eu.m724.tweaks.module.chat.ChatModule; +import eu.m724.tweaks.module.door.DoorKnockModule; +import eu.m724.tweaks.module.door.DoorOpenModule; +import eu.m724.tweaks.module.full.FullModule; +import eu.m724.tweaks.module.hardcore.HardcoreModule; +import eu.m724.tweaks.module.killswitch.KillswitchModule; +import eu.m724.tweaks.module.knockback.KnockbackModule; +import eu.m724.tweaks.module.motd.MotdModule; +import eu.m724.tweaks.module.ping.F3NameListener; +import eu.m724.tweaks.module.ping.PingChecker; +import eu.m724.tweaks.module.pomodoro.PomodoroModule; +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.worldborder.WorldBorderExpandModule; +import eu.m724.tweaks.module.worldborder.WorldBorderHideModule; import java.util.Locale; import java.util.logging.Level; diff --git a/src/main/java/eu/m724/tweaks/TweaksModule.java b/src/main/java/eu/m724/tweaks/module/TweaksModule.java similarity index 95% rename from src/main/java/eu/m724/tweaks/TweaksModule.java rename to src/main/java/eu/m724/tweaks/module/TweaksModule.java index a75bdea..c6e83c1 100644 --- a/src/main/java/eu/m724/tweaks/TweaksModule.java +++ b/src/main/java/eu/m724/tweaks/module/TweaksModule.java @@ -4,13 +4,16 @@ * in the project root for the full license text. */ -package eu.m724.tweaks; +package eu.m724.tweaks.module; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketEvent; +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.TweaksPlugin; import org.bukkit.command.CommandExecutor; import org.bukkit.event.Listener; diff --git a/src/main/java/eu/m724/tweaks/alert/Alert.java b/src/main/java/eu/m724/tweaks/module/alert/Alert.java similarity index 95% rename from src/main/java/eu/m724/tweaks/alert/Alert.java rename to src/main/java/eu/m724/tweaks/module/alert/Alert.java index be73459..2c802b6 100644 --- a/src/main/java/eu/m724/tweaks/alert/Alert.java +++ b/src/main/java/eu/m724/tweaks/module/alert/Alert.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.alert; +package eu.m724.tweaks.module.alert; import org.bukkit.Bukkit; import org.bukkit.Material; diff --git a/src/main/java/eu/m724/tweaks/alert/AlertCommand.java b/src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java similarity index 99% rename from src/main/java/eu/m724/tweaks/alert/AlertCommand.java rename to src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java index 2a5d821..2a17c77 100644 --- a/src/main/java/eu/m724/tweaks/alert/AlertCommand.java +++ b/src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.alert; +package eu.m724.tweaks.module.alert; import org.bukkit.Material; import org.bukkit.command.Command; diff --git a/src/main/java/eu/m724/tweaks/alert/AlertModule.java b/src/main/java/eu/m724/tweaks/module/alert/AlertModule.java similarity index 96% rename from src/main/java/eu/m724/tweaks/alert/AlertModule.java rename to src/main/java/eu/m724/tweaks/module/alert/AlertModule.java index b7df6a9..c900b86 100644 --- a/src/main/java/eu/m724/tweaks/alert/AlertModule.java +++ b/src/main/java/eu/m724/tweaks/module/alert/AlertModule.java @@ -4,12 +4,12 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.alert; +package eu.m724.tweaks.module.alert; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketContainer; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; diff --git a/src/main/java/eu/m724/tweaks/alert/AlertRunnable.java b/src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java similarity index 96% rename from src/main/java/eu/m724/tweaks/alert/AlertRunnable.java rename to src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java index d2c3400..9ce8989 100644 --- a/src/main/java/eu/m724/tweaks/alert/AlertRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.alert; +package eu.m724.tweaks.module.alert; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatMessageType; diff --git a/src/main/java/eu/m724/tweaks/auth/AuthCommands.java b/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java similarity index 98% rename from src/main/java/eu/m724/tweaks/auth/AuthCommands.java rename to src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java index d33767c..88f3874 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthCommands.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.auth; +package eu.m724.tweaks.module.auth; import eu.m724.tweaks.Language; import eu.m724.tweaks.TweaksConfig; diff --git a/src/main/java/eu/m724/tweaks/auth/AuthListener.java b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java similarity index 96% rename from src/main/java/eu/m724/tweaks/auth/AuthListener.java rename to src/main/java/eu/m724/tweaks/module/auth/AuthListener.java index 1ed2a4f..f61cb8c 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthListener.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.auth; +package eu.m724.tweaks.module.auth; import eu.m724.tweaks.Language; import eu.m724.tweaks.TweaksConfig; diff --git a/src/main/java/eu/m724/tweaks/auth/AuthModule.java b/src/main/java/eu/m724/tweaks/module/auth/AuthModule.java similarity index 85% rename from src/main/java/eu/m724/tweaks/auth/AuthModule.java rename to src/main/java/eu/m724/tweaks/module/auth/AuthModule.java index 43d0fcf..f09af23 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthModule.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.auth; +package eu.m724.tweaks.module.auth; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; public class AuthModule extends TweaksModule { @Override diff --git a/src/main/java/eu/m724/tweaks/auth/AuthStorage.java b/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java similarity index 98% rename from src/main/java/eu/m724/tweaks/auth/AuthStorage.java rename to src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java index 85fceed..7eb9c64 100644 --- a/src/main/java/eu/m724/tweaks/auth/AuthStorage.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.auth; +package eu.m724.tweaks.module.auth; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatCommands.java b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java similarity index 99% rename from src/main/java/eu/m724/tweaks/chat/ChatCommands.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java index 1ed2180..d6fa1ba 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatCommands.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.chat; +package eu.m724.tweaks.module.chat; import eu.m724.tweaks.Language; import net.md_5.bungee.api.ChatColor; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java b/src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java similarity index 96% rename from src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java index b152f9e..016beeb 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.chat; +package eu.m724.tweaks.module.chat; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatListener.java b/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java similarity index 99% rename from src/main/java/eu/m724/tweaks/chat/ChatListener.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatListener.java index b94d770..20d8c2c 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatListener.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.chat; +package eu.m724.tweaks.module.chat; import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatColor; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatModule.java b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java similarity index 98% rename from src/main/java/eu/m724/tweaks/chat/ChatModule.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatModule.java index eaad314..74f823d 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatModule.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.chat; +package eu.m724.tweaks.module.chat; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.NamespacedKey; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatRoom.java b/src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java similarity index 97% rename from src/main/java/eu/m724/tweaks/chat/ChatRoom.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java index a659694..3eb34fe 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatRoom.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.chat; +package eu.m724.tweaks.module.chat; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; diff --git a/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java b/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java similarity index 97% rename from src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java rename to src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java index a160311..28425d5 100644 --- a/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.chat; +package eu.m724.tweaks.module.chat; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; diff --git a/src/main/java/eu/m724/tweaks/compass/CompassModule.java b/src/main/java/eu/m724/tweaks/module/compass/CompassModule.java similarity index 98% rename from src/main/java/eu/m724/tweaks/compass/CompassModule.java rename to src/main/java/eu/m724/tweaks/module/compass/CompassModule.java index 23dfcf7..5516f93 100644 --- a/src/main/java/eu/m724/tweaks/compass/CompassModule.java +++ b/src/main/java/eu/m724/tweaks/module/compass/CompassModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.compass; +package eu.m724.tweaks.module.compass; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.ComponentBuilder; diff --git a/src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java b/src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java similarity index 89% rename from src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java rename to src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java index f4d3b19..9e2fec2 100644 --- a/src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java +++ b/src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.compass; +package eu.m724.tweaks.module.compass; import org.bukkit.entity.Player; diff --git a/src/main/java/eu/m724/tweaks/door/DoorKnockModule.java b/src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java similarity index 96% rename from src/main/java/eu/m724/tweaks/door/DoorKnockModule.java rename to src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java index 2627c18..2213363 100644 --- a/src/main/java/eu/m724/tweaks/door/DoorKnockModule.java +++ b/src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.door; +package eu.m724.tweaks.module.door; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; diff --git a/src/main/java/eu/m724/tweaks/door/DoorOpenModule.java b/src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java similarity index 97% rename from src/main/java/eu/m724/tweaks/door/DoorOpenModule.java rename to src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java index e6773df..7705c68 100644 --- a/src/main/java/eu/m724/tweaks/door/DoorOpenModule.java +++ b/src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.door; +package eu.m724.tweaks.module.door; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; diff --git a/src/main/java/eu/m724/tweaks/full/FullModule.java b/src/main/java/eu/m724/tweaks/module/full/FullModule.java similarity index 89% rename from src/main/java/eu/m724/tweaks/full/FullModule.java rename to src/main/java/eu/m724/tweaks/module/full/FullModule.java index 8b40269..e9569f2 100644 --- a/src/main/java/eu/m724/tweaks/full/FullModule.java +++ b/src/main/java/eu/m724/tweaks/module/full/FullModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.full; +package eu.m724.tweaks.module.full; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerLoginEvent; diff --git a/src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java b/src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java similarity index 95% rename from src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java rename to src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java index b0df9a4..387d51b 100644 --- a/src/main/java/eu/m724/tweaks/hardcore/HardcoreModule.java +++ b/src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java @@ -4,12 +4,12 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.hardcore; +package eu.m724.tweaks.module.hardcore; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import net.minecraft.world.level.levelgen.RandomSupport; import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus; diff --git a/src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java b/src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java similarity index 97% rename from src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java rename to src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java index b511ab9..9756b88 100644 --- a/src/main/java/eu/m724/tweaks/killswitch/KillswitchModule.java +++ b/src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java @@ -4,13 +4,13 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.killswitch; +package eu.m724.tweaks.module.killswitch; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; diff --git a/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java b/src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java similarity index 93% rename from src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java rename to src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java index 40039b6..311c30a 100644 --- a/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java +++ b/src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.killswitch; +package eu.m724.tweaks.module.killswitch; import org.bukkit.scheduler.BukkitRunnable; diff --git a/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java b/src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java similarity index 96% rename from src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java rename to src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java index 6fe128b..29092fd 100644 --- a/src/main/java/eu/m724/tweaks/knockback/KnockbackModule.java +++ b/src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java @@ -4,10 +4,10 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.knockback; +package eu.m724.tweaks.module.knockback; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/eu/m724/tweaks/motd/MotdModule.java b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java similarity index 98% rename from src/main/java/eu/m724/tweaks/motd/MotdModule.java rename to src/main/java/eu/m724/tweaks/module/motd/MotdModule.java index 03043fb..e02e28a 100644 --- a/src/main/java/eu/m724/tweaks/motd/MotdModule.java +++ b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.motd; +package eu.m724.tweaks.module.motd; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.*; @@ -14,7 +14,7 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.SharedConstants; diff --git a/src/main/java/eu/m724/tweaks/ping/F3NameListener.java b/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java similarity index 98% rename from src/main/java/eu/m724/tweaks/ping/F3NameListener.java rename to src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java index 9577841..c4f7e00 100644 --- a/src/main/java/eu/m724/tweaks/ping/F3NameListener.java +++ b/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.ping; +package eu.m724.tweaks.module.ping; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; diff --git a/src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java b/src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java similarity index 96% rename from src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java rename to src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java index 45fa7bd..d88d340 100644 --- a/src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java +++ b/src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.ping; +package eu.m724.tweaks.module.ping; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; diff --git a/src/main/java/eu/m724/tweaks/ping/MsptChecker.java b/src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java similarity index 89% rename from src/main/java/eu/m724/tweaks/ping/MsptChecker.java rename to src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java index dec46a0..a030c2d 100644 --- a/src/main/java/eu/m724/tweaks/ping/MsptChecker.java +++ b/src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.ping; +package eu.m724.tweaks.module.ping; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; diff --git a/src/main/java/eu/m724/tweaks/ping/PingChecker.java b/src/main/java/eu/m724/tweaks/module/ping/PingChecker.java similarity index 94% rename from src/main/java/eu/m724/tweaks/ping/PingChecker.java rename to src/main/java/eu/m724/tweaks/module/ping/PingChecker.java index e43ef04..c1c61e6 100644 --- a/src/main/java/eu/m724/tweaks/ping/PingChecker.java +++ b/src/main/java/eu/m724/tweaks/module/ping/PingChecker.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.ping; +package eu.m724.tweaks.module.ping; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/eu/m724/tweaks/ping/PingCommands.java b/src/main/java/eu/m724/tweaks/module/ping/PingCommands.java similarity index 94% rename from src/main/java/eu/m724/tweaks/ping/PingCommands.java rename to src/main/java/eu/m724/tweaks/module/ping/PingCommands.java index 01d9a1c..1e0f31d 100644 --- a/src/main/java/eu/m724/tweaks/ping/PingCommands.java +++ b/src/main/java/eu/m724/tweaks/module/ping/PingCommands.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.ping; +package eu.m724.tweaks.module.ping; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; diff --git a/src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java b/src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java similarity index 95% rename from src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java rename to src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java index f41285f..f8eb30c 100644 --- a/src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java +++ b/src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.ping; +package eu.m724.tweaks.module.ping; import org.bukkit.entity.Player; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java similarity index 96% rename from src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java index 3aba1be..7b7954c 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.pomodoro; +package eu.m724.tweaks.module.pomodoro; public class PlayerPomodoro { private int pomodori = 0; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java similarity index 95% rename from src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java index fc5af95..55f9685 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.pomodoro; +package eu.m724.tweaks.module.pomodoro; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java similarity index 96% rename from src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java index 9859e64..bc04be2 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.pomodoro; +package eu.m724.tweaks.module.pomodoro; import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.chat.ComponentBuilder; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java similarity index 85% rename from src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java index 564e638..74cdedf 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroModule.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.pomodoro; +package eu.m724.tweaks.module.pomodoro; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; public class PomodoroModule extends TweaksModule { @Override diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java similarity index 95% rename from src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java index 3f28def..89faf34 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.pomodoro; +package eu.m724.tweaks.module.pomodoro; import eu.m724.tweaks.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; diff --git a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java b/src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java similarity index 96% rename from src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java rename to src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java index 10044f9..43cb412 100644 --- a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.pomodoro; +package eu.m724.tweaks.module.pomodoro; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; diff --git a/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java b/src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java similarity index 98% rename from src/main/java/eu/m724/tweaks/redstone/GatewayItem.java rename to src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java index 4082bf3..29863dc 100644 --- a/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.redstone; +package eu.m724.tweaks.module.redstone; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java similarity index 95% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java index f1c6b28..c489a8e 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +package eu.m724.tweaks.module.redstone; import org.bukkit.Bukkit; import org.bukkit.command.Command; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java similarity index 98% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java index d7ae10f..9f17572 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +package eu.m724.tweaks.module.redstone; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java similarity index 97% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java index bff3c1e..0e1abfa 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +package eu.m724.tweaks.module.redstone; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java similarity index 97% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java index 30cd13f..36e4f86 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneModule.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java @@ -4,11 +4,11 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.redstone; +package eu.m724.tweaks.module.redstone; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.TweaksConfig; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import java.io.IOException; import java.net.*; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java similarity index 94% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java index f036f49..2ab5410 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +package eu.m724.tweaks.module.redstone; import org.bukkit.scheduler.BukkitRunnable; diff --git a/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java similarity index 96% rename from src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java rename to src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java index 8c812ea..3b2bc38 100644 --- a/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.redstone; +package eu.m724.tweaks.module.redstone; import com.google.common.primitives.Ints; import eu.m724.tweaks.DebugLogger; diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java similarity index 98% rename from src/main/java/eu/m724/tweaks/sleep/SleepListener.java rename to src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java index 129a02b..9dc5986 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepListener.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.sleep; +package eu.m724.tweaks.module.sleep; import eu.m724.tweaks.TweaksConfig; import org.bukkit.GameRule; diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepModule.java b/src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java similarity index 85% rename from src/main/java/eu/m724/tweaks/sleep/SleepModule.java rename to src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java index d467338..e2d45f8 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepModule.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.sleep; +package eu.m724.tweaks.module.sleep; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; public class SleepModule extends TweaksModule { @Override diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepState.java b/src/main/java/eu/m724/tweaks/module/sleep/SleepState.java similarity index 74% rename from src/main/java/eu/m724/tweaks/sleep/SleepState.java rename to src/main/java/eu/m724/tweaks/module/sleep/SleepState.java index f810e9e..e8f0991 100644 --- a/src/main/java/eu/m724/tweaks/sleep/SleepState.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/SleepState.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.sleep; +package eu.m724.tweaks.module.sleep; public class SleepState { static int playersSleeping; diff --git a/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java b/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java similarity index 95% rename from src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java rename to src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java index 41f91d5..80b6f3e 100644 --- a/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java @@ -1,10 +1,10 @@ /* - * Copyright (C) 2024 Minecon724 + * 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.sleep; +package eu.m724.tweaks.module.sleep; import org.bukkit.GameRule; import org.bukkit.Server; diff --git a/src/main/java/eu/m724/tweaks/swing/SwingModule.java b/src/main/java/eu/m724/tweaks/module/swing/SwingModule.java similarity index 96% rename from src/main/java/eu/m724/tweaks/swing/SwingModule.java rename to src/main/java/eu/m724/tweaks/module/swing/SwingModule.java index fdd2465..392c13f 100644 --- a/src/main/java/eu/m724/tweaks/swing/SwingModule.java +++ b/src/main/java/eu/m724/tweaks/module/swing/SwingModule.java @@ -4,10 +4,10 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.swing; +package eu.m724.tweaks.module.swing; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import org.bukkit.Material; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Entity; diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java b/src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java similarity index 95% rename from src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java rename to src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java index a801093..8e399be 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java +++ b/src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java @@ -4,11 +4,11 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater; +package eu.m724.tweaks.module.updater; import eu.m724.tweaks.Language; -import eu.m724.tweaks.updater.backend.UpdateChecker; -import eu.m724.tweaks.updater.object.VersionedResource; +import eu.m724.tweaks.module.updater.backend.UpdateChecker; +import eu.m724.tweaks.module.updater.object.VersionedResource; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java b/src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java similarity index 89% rename from src/main/java/eu/m724/tweaks/updater/UpdaterModule.java rename to src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java index c76522c..6c39e17 100644 --- a/src/main/java/eu/m724/tweaks/updater/UpdaterModule.java +++ b/src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java @@ -4,15 +4,15 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater; +package eu.m724.tweaks.module.updater; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksModule; -import eu.m724.tweaks.updater.backend.UpdateChecker; -import eu.m724.tweaks.updater.backend.VersionCache; -import eu.m724.tweaks.updater.object.ResourceVersion; -import eu.m724.tweaks.updater.object.SpigotResource; -import eu.m724.tweaks.updater.object.VersionedResource; +import eu.m724.tweaks.module.TweaksModule; +import eu.m724.tweaks.module.updater.backend.UpdateChecker; +import eu.m724.tweaks.module.updater.backend.VersionCache; +import eu.m724.tweaks.module.updater.object.ResourceVersion; +import eu.m724.tweaks.module.updater.object.SpigotResource; +import eu.m724.tweaks.module.updater.object.VersionedResource; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java b/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java similarity index 97% rename from src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java rename to src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java index 72f3ac6..4585a3a 100644 --- a/src/main/java/eu/m724/tweaks/updater/backend/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java @@ -4,11 +4,11 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.backend; +package eu.m724.tweaks.module.updater.backend; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; -import eu.m724.tweaks.updater.object.VersionedResource; +import eu.m724.tweaks.module.updater.object.VersionedResource; import org.bukkit.scheduler.BukkitRunnable; import java.io.File; diff --git a/src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java similarity index 96% rename from src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java rename to src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java index a2f0797..e6952ad 100644 --- a/src/main/java/eu/m724/tweaks/updater/backend/VersionCache.java +++ b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.backend; +package eu.m724.tweaks.module.updater.backend; -import eu.m724.tweaks.updater.object.ResourceVersion; +import eu.m724.tweaks.module.updater.object.ResourceVersion; import java.io.FileInputStream; import java.io.FileOutputStream; diff --git a/src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java similarity index 94% rename from src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java rename to src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java index 6cd6262..39fb543 100644 --- a/src/main/java/eu/m724/tweaks/updater/backend/VersionScanner.java +++ b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java @@ -4,17 +4,17 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.backend; +package eu.m724.tweaks.module.updater.backend; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.updater.object.SpigotResource; -import eu.m724.tweaks.updater.object.ResourceVersion; -import eu.m724.tweaks.updater.object.UpdateDescription; -import eu.m724.tweaks.updater.object.VersionedResource; +import eu.m724.tweaks.module.updater.object.SpigotResource; +import eu.m724.tweaks.module.updater.object.ResourceVersion; +import eu.m724.tweaks.module.updater.object.UpdateDescription; +import eu.m724.tweaks.module.updater.object.VersionedResource; import java.net.URI; import java.net.URISyntaxException; diff --git a/src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java b/src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java similarity index 93% rename from src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java rename to src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java index 6bebcea..90efb34 100644 --- a/src/main/java/eu/m724/tweaks/updater/object/ResourceVersion.java +++ b/src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.object; +package eu.m724.tweaks.module.updater.object; import java.util.Objects; diff --git a/src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java b/src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java similarity index 87% rename from src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java rename to src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java index c2c7a8a..28b0987 100644 --- a/src/main/java/eu/m724/tweaks/updater/object/SpigotResource.java +++ b/src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.object; +package eu.m724.tweaks.module.updater.object; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java b/src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java similarity index 85% rename from src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java rename to src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java index 508b8bd..d22f588 100644 --- a/src/main/java/eu/m724/tweaks/updater/object/UpdateDescription.java +++ b/src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.object; +package eu.m724.tweaks.module.updater.object; public record UpdateDescription( String title, diff --git a/src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java b/src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java similarity index 87% rename from src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java rename to src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java index f140bb9..4c274e3 100644 --- a/src/main/java/eu/m724/tweaks/updater/object/VersionedResource.java +++ b/src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.updater.object; +package eu.m724.tweaks.module.updater.object; public record VersionedResource( SpigotResource resource, diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java b/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java similarity index 93% rename from src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java rename to src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java index 2f735ad..b4a4a30 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpandModule.java +++ b/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java @@ -4,9 +4,9 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.worldborder; +package eu.m724.tweaks.module.worldborder; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import net.minecraft.server.level.ServerLevel; import org.bukkit.craftbukkit.v1_21_R3.CraftWorld; import org.bukkit.event.EventHandler; diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java b/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java similarity index 95% rename from src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java rename to src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java index 0400534..52f90cd 100644 --- a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHideModule.java +++ b/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java @@ -4,11 +4,11 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.worldborder; +package eu.m724.tweaks.module.worldborder; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; -import eu.m724.tweaks.TweaksModule; +import eu.m724.tweaks.module.TweaksModule; import java.nio.ByteBuffer; From 29f79a87710b400302ba22a606b90dc74df33a50 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 24 Jan 2025 18:42:39 +0100 Subject: [PATCH 63/89] Improve config loader --- .../java/eu/m724/tweaks/TweaksConfig.java | 165 ------------------ .../java/eu/m724/tweaks/TweaksPlugin.java | 9 +- .../eu/m724/tweaks/config/ConfigLoader.java | 143 +++++++++++++++ .../tweaks/config/MissingFieldsException.java | 22 +++ .../eu/m724/tweaks/config/TweaksConfig.java | 103 +++++++++++ .../eu/m724/tweaks/module/TweaksModule.java | 2 +- .../m724/tweaks/module/auth/AuthCommands.java | 2 +- .../m724/tweaks/module/auth/AuthListener.java | 2 +- .../m724/tweaks/module/chat/ChatListener.java | 2 +- .../m724/tweaks/module/motd/MotdModule.java | 2 +- .../tweaks/module/ping/F3NameListener.java | 2 +- .../module/pomodoro/PomodoroListener.java | 2 +- .../module/pomodoro/PomodoroRunnable.java | 2 +- .../module/redstone/RedstoneModule.java | 2 +- .../tweaks/module/sleep/SleepListener.java | 2 +- 15 files changed, 285 insertions(+), 177 deletions(-) delete mode 100644 src/main/java/eu/m724/tweaks/TweaksConfig.java create mode 100644 src/main/java/eu/m724/tweaks/config/ConfigLoader.java create mode 100644 src/main/java/eu/m724/tweaks/config/MissingFieldsException.java create mode 100644 src/main/java/eu/m724/tweaks/config/TweaksConfig.java diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java deleted file mode 100644 index 584d0fe..0000000 --- a/src/main/java/eu/m724/tweaks/TweaksConfig.java +++ /dev/null @@ -1,165 +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; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.plugin.Plugin; - -import java.util.Map; - -public record TweaksConfig( - boolean metrics, - boolean debug, - String locale, - - boolean worldborderExpand, - boolean worldborderHide, - - boolean brandEnabled, - String brandText, - boolean brandShowPing, - boolean brandShowMspt, - - boolean doorDoubleOpen, - boolean doorKnocking, - - boolean motdEnabled, - String motdSet, - - boolean chatEnabled, - boolean chatLocalEvents, - String chatDefaultName, - int chatRadius, - - boolean compassEnabled, - int compassWidth, - int compassPrecision, - - boolean pomodoroEnabled, - boolean pomodoroForce, - - boolean updaterEnabled, - - boolean hardcoreEnabled, - double hardcoreChance, - - boolean sleepEnabled, - boolean sleepInstant, - double sleepHeal, - - boolean authEnabled, - boolean authForce, - String authDomain, - - boolean redstoneEnabled, - String redstoneListen, - - Map knockbackModifiers, - - boolean killswitchEnabled, - String killswitchListen, - - boolean swingEnabled -) { - public static final int CONFIG_VERSION = 2; - private static TweaksConfig config; - - public static TweaksConfig getConfig() { - return config; - } - - public static TweaksConfig load(Plugin plugin) { - plugin.saveDefaultConfig(); - FileConfiguration config = plugin.getConfig(); - - int configVersion = config.getInt("magic number don't modify this", 0); - RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION)); - - if (configVersion == 0) { - throw exception; - } else if (configVersion < CONFIG_VERSION) { - throw new RuntimeException("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception); - } else if (configVersion > CONFIG_VERSION) { - throw new RuntimeException("Did you downgrade the plugin? Remove config.yml and let the plugin re-create it", exception); - } - - boolean metrics = config.getBoolean("metrics"); - boolean debug = config.getBoolean("debug", false); - String locale = config.getString("locale", "US"); - - boolean worldborderExpand = config.getBoolean("worldborder.expand"); - boolean worldborderHide = config.getBoolean("worldborder.hide"); - - boolean brandEnabled = config.getBoolean("brand.enabled"); - String brandText = config.getString("brand.text"); - boolean brandShowPing = config.getBoolean("brand.showPing"); - boolean brandShowMspt = config.getBoolean("brand.showMspt"); - - boolean doorDoubleOpen = config.getBoolean("doors.doubleOpen"); - boolean doorKnocking = config.getBoolean("doors.knocking"); - - String motdSet = config.getString("motd.set"); - boolean motdEnabled = !(motdSet.equals("false") || motdSet.isBlank()); - - boolean chatEnabled = config.getBoolean("chat.enabled"); - boolean chatLocalEvents = config.getBoolean("chat.localEvents"); - String chatDefaultName = config.getString("chat.defaultName"); - int chatRadius = config.getInt("chat.radius"); - - boolean compassEnabled = config.getBoolean("compass.enabled"); - int compassWidth = config.getInt("compass.width"); - int compassPrecision = config.getInt("compass.precision"); - - boolean pomodoroEnabled = config.getBoolean("pomodoro.enabled"); - boolean pomodoroForce = config.getBoolean("pomodoro.force"); - - boolean updaterEnabled = config.getBoolean("updater.enabled"); - - boolean hardcoreEnabled = config.getBoolean("hardcore.enabled"); - double hardcoreChance = config.getDouble("hardcore.chance"); - - boolean sleepEnabled = config.getBoolean("sleep.enabled"); - boolean sleepInstant = config.getBoolean("sleep.instant"); - double sleepHeal = config.getDouble("sleep.heal"); - - boolean authEnabled = config.getBoolean("auth.enabled"); - boolean authForce = config.getBoolean("auth.force"); - String authHostname = config.getString("auth.domain"); - - boolean redstoneEnabled = config.getBoolean("retstone.enabled"); - String redstoneListen = config.getString("retstone.listen"); - - // this is processed when initing - Map knockbackModifiers = config.getConfigurationSection("knockback").getValues(false); - - boolean killswitchEnabled = config.getBoolean("killswitch.enabled"); - String killswitchListen = config.getString("killswitch.listen"); - - boolean swingEnabled = config.getBoolean("swing.enabled"); - - TweaksConfig.config = new TweaksConfig( - metrics, debug, locale, - worldborderExpand, worldborderHide, - brandEnabled, brandText, brandShowPing, brandShowMspt, - doorDoubleOpen, doorKnocking, - motdEnabled, motdSet, - chatEnabled, chatLocalEvents, chatDefaultName, chatRadius, - compassEnabled, compassWidth, compassPrecision, - pomodoroEnabled, pomodoroForce, - updaterEnabled, - hardcoreEnabled, hardcoreChance, - sleepEnabled, sleepInstant, sleepHeal, - authEnabled, authForce, authHostname, - redstoneEnabled, redstoneListen, - knockbackModifiers, - killswitchEnabled, killswitchListen, - swingEnabled - ); - - return TweaksConfig.config; - } -} \ 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 1f25ca3..8c6430e 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -7,6 +7,7 @@ package eu.m724.tweaks; import eu.m724.mstats.MStatsPlugin; +import eu.m724.tweaks.config.TweaksConfig; import eu.m724.tweaks.module.TweaksModule; import eu.m724.tweaks.module.alert.AlertModule; import eu.m724.tweaks.module.auth.AuthModule; @@ -46,7 +47,12 @@ public class TweaksPlugin extends MStatsPlugin { return; } - TweaksConfig config = TweaksConfig.load(this); + TweaksConfig config; + try { + config = TweaksConfig.load(this); + } catch (Exception e) { + throw new RuntimeException("Exception loading config", e); + } getLogger().setLevel(config.debug() ? Level.FINEST : Level.INFO); DebugLogger.logger = getLogger(); @@ -84,7 +90,6 @@ public class TweaksPlugin extends MStatsPlugin { if (config.worldborderExpand()) { TweaksModule.init(WorldBorderExpandModule.class); - } if (config.chatEnabled()) { diff --git a/src/main/java/eu/m724/tweaks/config/ConfigLoader.java b/src/main/java/eu/m724/tweaks/config/ConfigLoader.java new file mode 100644 index 0000000..36d7cd4 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/config/ConfigLoader.java @@ -0,0 +1,143 @@ +/* + * 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.config; + +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class ConfigLoader { + private final FileConfiguration configuration; + private final List missing = new ArrayList<>(); + + ConfigLoader(FileConfiguration configuration) { + this.configuration = configuration; + } + + List getMissing() { + return missing; + } + + TweaksConfig load() { + boolean metrics = configuration.getBoolean("metrics", false); + boolean debug = configuration.getBoolean("debug", false); + String locale = configuration.getString("locale", "US"); + + boolean worldborderExpand = getBoolean("worldborder.expand"); + boolean worldborderHide = getBoolean("worldborder.hide"); + + boolean brandEnabled = getBoolean("brand.enabled"); + String brandText = getString("brand.text"); + boolean brandShowPing = getBoolean("brand.showPing"); + boolean brandShowMspt = getBoolean("brand.showMspt"); + + boolean doorDoubleOpen = getBoolean("doors.doubleOpen"); + boolean doorKnocking = getBoolean("doors.knocking"); + + String motdSet = getString("motd.set"); + boolean motdEnabled = !(motdSet.equals("false") || motdSet.isBlank()); + + boolean chatEnabled = getBoolean("chat.enabled"); + boolean chatLocalEvents = getBoolean("chat.localEvents"); + String chatDefaultName = getString("chat.defaultName"); + int chatRadius = getInt("chat.radius"); + + boolean compassEnabled = getBoolean("compass.enabled"); + int compassWidth = getInt("compass.width"); + int compassPrecision = getInt("compass.precision"); + + boolean pomodoroEnabled = getBoolean("pomodoro.enabled"); + boolean pomodoroForce = getBoolean("pomodoro.force"); + + boolean updaterEnabled = getBoolean("updater.enabled"); + + boolean hardcoreEnabled = getBoolean("hardcore.enabled"); + double hardcoreChance = getDouble("hardcore.chance"); + + boolean sleepEnabled = getBoolean("sleep.enabled"); + boolean sleepInstant = getBoolean("sleep.instant"); + double sleepHeal = getDouble("sleep.heal"); + + boolean authEnabled = getBoolean("auth.enabled"); + boolean authForce = getBoolean("auth.force"); + String authHostname = getString("auth.domain"); + + boolean redstoneEnabled = getBoolean("retstone.enabled"); + String redstoneListen = getString("retstone.listen"); + + // this is processed when initing knockback module + Map knockbackModifiers = getValues("knockback"); + + boolean killswitchEnabled = getBoolean("killswitch.enabled"); + String killswitchListen = getString("killswitch.listen"); + + boolean swingEnabled = getBoolean("swing.enabled"); + + return new TweaksConfig( + metrics, debug, locale, + worldborderExpand, worldborderHide, + brandEnabled, brandText, brandShowPing, brandShowMspt, + doorDoubleOpen, doorKnocking, + motdEnabled, motdSet, + chatEnabled, chatLocalEvents, chatDefaultName, chatRadius, + compassEnabled, compassWidth, compassPrecision, + pomodoroEnabled, pomodoroForce, + updaterEnabled, + hardcoreEnabled, hardcoreChance, + sleepEnabled, sleepInstant, sleepHeal, + authEnabled, authForce, authHostname, + redstoneEnabled, redstoneListen, + knockbackModifiers, + killswitchEnabled, killswitchListen, + swingEnabled + ); + } + + private double getDouble(String key) { + if (!configuration.contains(key)) + missing.add(key); + + // we return the whatever default value + return configuration.getDouble(key); + } + + private int getInt(String key) { + if (!configuration.contains(key)) + missing.add(key); + + return configuration.getInt(key); + } + + private boolean getBoolean(String key) { + if (!configuration.contains(key)) + missing.add(key); + + return configuration.getBoolean(key); + } + + private String getString(String key) { + if (!configuration.contains(key)) + missing.add(key); + + return configuration.getString(key); + } + + private Map getValues(String key) { + var cs = configuration.getConfigurationSection(key); + + if (cs == null) { + missing.add(key); + // the default is null, which is bad + return new HashMap<>(); + } + + return cs.getValues(false); + } +} diff --git a/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java b/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java new file mode 100644 index 0000000..24f1be0 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java @@ -0,0 +1,22 @@ +/* + * 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.config; + +import java.util.List; + +class MissingFieldsException extends Exception { + private final List missing; + + MissingFieldsException(List missing) { + this.missing = missing; + } + + @Override + public String getMessage() { + return String.join(", ", missing); + } +} diff --git a/src/main/java/eu/m724/tweaks/config/TweaksConfig.java b/src/main/java/eu/m724/tweaks/config/TweaksConfig.java new file mode 100644 index 0000000..7442813 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/config/TweaksConfig.java @@ -0,0 +1,103 @@ +/* + * 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.config; + +import org.bukkit.plugin.Plugin; + +import java.util.Map; + +public record TweaksConfig( + boolean metrics, + boolean debug, + String locale, + + boolean worldborderExpand, + boolean worldborderHide, + + boolean brandEnabled, + String brandText, + boolean brandShowPing, + boolean brandShowMspt, + + boolean doorDoubleOpen, + boolean doorKnocking, + + boolean motdEnabled, + String motdSet, + + boolean chatEnabled, + boolean chatLocalEvents, + String chatDefaultName, + int chatRadius, + + boolean compassEnabled, + int compassWidth, + int compassPrecision, + + boolean pomodoroEnabled, + boolean pomodoroForce, + + boolean updaterEnabled, + + boolean hardcoreEnabled, + double hardcoreChance, + + boolean sleepEnabled, + boolean sleepInstant, + double sleepHeal, + + boolean authEnabled, + boolean authForce, + String authDomain, + + boolean redstoneEnabled, + String redstoneListen, + + Map knockbackModifiers, + + boolean killswitchEnabled, + String killswitchListen, + + boolean swingEnabled +) { + public static final int CONFIG_VERSION = 2; + private static TweaksConfig config; + + public static TweaksConfig getConfig() { + return config; + } + + public static TweaksConfig load(Plugin plugin) throws Exception { + plugin.saveDefaultConfig(); + var pluginConfig = plugin.getConfig(); + + var configVersion = pluginConfig.getInt("magic number don't modify this", 0); + var exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION)); + + if (configVersion == 0) { + throw exception; + } else if (configVersion < CONFIG_VERSION) { + throw new Exception("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception); + } else if (configVersion > CONFIG_VERSION) { + throw new Exception("Did you downgrade the plugin? Delete config.yml and let the plugin re-create it", exception); + } + + var loader = new ConfigLoader(pluginConfig); + var config = loader.load(); + + if (loader.getMissing().isEmpty()) { + TweaksConfig.config = config; + return config; + } else { + throw new Exception( + "One or more fields are missing from config.yml. Did you follow the update instructions? https://www.spigotmc.org/resources/tweaks724.121057/updates", + new MissingFieldsException(loader.getMissing()) + ); + } + } + +} \ No newline at end of file diff --git a/src/main/java/eu/m724/tweaks/module/TweaksModule.java b/src/main/java/eu/m724/tweaks/module/TweaksModule.java index c6e83c1..e3f4de0 100644 --- a/src/main/java/eu/m724/tweaks/module/TweaksModule.java +++ b/src/main/java/eu/m724/tweaks/module/TweaksModule.java @@ -12,7 +12,7 @@ import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketEvent; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import eu.m724.tweaks.TweaksPlugin; import org.bukkit.command.CommandExecutor; import org.bukkit.event.Listener; diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java b/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java index 88f3874..5aae83f 100644 --- a/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java @@ -7,7 +7,7 @@ package eu.m724.tweaks.module.auth; import eu.m724.tweaks.Language; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java index f61cb8c..bc4634c 100644 --- a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java @@ -7,7 +7,7 @@ package eu.m724.tweaks.module.auth; import eu.m724.tweaks.Language; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java b/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java index 20d8c2c..21b65f9 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java @@ -6,7 +6,7 @@ package eu.m724.tweaks.module.chat; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ComponentBuilder; diff --git a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java index e02e28a..b0534cd 100644 --- a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java +++ b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java @@ -13,7 +13,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; diff --git a/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java b/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java index c4f7e00..bf43d14 100644 --- a/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java +++ b/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java @@ -10,7 +10,7 @@ import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.*; import com.comphenix.protocol.reflect.StructureModifier; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import net.minecraft.network.protocol.common.custom.BrandPayload; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java index bc04be2..077e36e 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java @@ -6,7 +6,7 @@ package eu.m724.tweaks.module.pomodoro; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java index 89faf34..6612d6d 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java @@ -6,7 +6,7 @@ package eu.m724.tweaks.module.pomodoro; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; import org.bukkit.Sound; diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java index 36e4f86..b574786 100644 --- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java +++ b/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java @@ -7,7 +7,7 @@ package eu.m724.tweaks.module.redstone; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import eu.m724.tweaks.module.TweaksModule; import java.io.IOException; diff --git a/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java index 9dc5986..b1d0f85 100644 --- a/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java @@ -6,7 +6,7 @@ package eu.m724.tweaks.module.sleep; -import eu.m724.tweaks.TweaksConfig; +import eu.m724.tweaks.config.TweaksConfig; import org.bukkit.GameRule; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Player; From 2a65e9dbcbd30021faa2bd36a70a7ca2d0dcabb8 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 25 Jan 2025 20:32:17 +0100 Subject: [PATCH 64/89] Fix small debug log mistake --- .../eu/m724/tweaks/module/updater/backend/VersionScanner.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java index 39fb543..2eabcea 100644 --- a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java +++ b/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java @@ -43,7 +43,6 @@ public class VersionScanner extends CompletableFuture { } private void start() { - //System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName()); DebugLogger.finer("Scanning %s (#%d) from page %d", resource.name(), resource.resourceId(), fromPage); try (ExecutorService executor = Executors.newSingleThreadExecutor()) { @@ -54,7 +53,7 @@ public class VersionScanner extends CompletableFuture { int page; for (page = fromPage; page < 1000; page++) { - DebugLogger.finer("Scan %s now at page %d", resource.name(), fromPage); + DebugLogger.finer("Scan %s now at page %d", resource.name(), page); String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId()); From 2761ed87570f650b9e1bc7e64f44157e103f36e5 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 26 Jan 2025 12:41:40 +0100 Subject: [PATCH 65/89] Slightly smarter updater notice --- .../module/updater/backend/UpdateChecker.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java b/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java index 4585a3a..92afcb1 100644 --- a/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java +++ b/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java @@ -39,6 +39,7 @@ public class UpdateChecker extends BukkitRunnable { DebugLogger.fine("Checking for updates"); lastChecked = System.currentTimeMillis(); availableUpdates.clear(); + var errors = 0; for (VersionedResource versionedResource : Set.copyOf(resources)) { String pluginName = versionedResource.resource().plugin().getName(); @@ -50,10 +51,17 @@ public class UpdateChecker extends BukkitRunnable { resources.remove(versionedResource); if (newResource.running() == null) { - DebugLogger.warning("Unable to find installed version of %s", pluginName); - if (versionedResource.running() != null) { - DebugLogger.warning("Did you downgrade %s? If so, clear cache", pluginName); + var pluginVersion = versionedResource.resource().plugin().getDescription().getVersion(); + var message = ""; + + if (pluginVersion.endsWith("-SNAPSHOT")) { + message = "Is it a development build?"; + } else if (versionedResource.running() != null) { + message = "Did you downgrade it? If so, clear cache (delete Tweaks724/storage/cache/updater)"; } + + DebugLogger.warning("This version of %s doesn't exist on SpigotMC. %s", pluginName, message); + errors++; } else { if (!newResource.running().equals(newResource.latest())) { availableUpdates.add(newResource); @@ -66,6 +74,10 @@ public class UpdateChecker extends BukkitRunnable { DebugLogger.severe("Unable to refresh %s: %s".formatted(pluginName, e.getMessage())); } } + + if (errors > 0) { + DebugLogger.info("To disable the updater for specific plugins, refer to updater_config.yml"); + } } private void alert() { From 9345efe1d45716419785191db41b760ea37911c9 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 27 Jan 2025 08:45:52 +0100 Subject: [PATCH 66/89] Initial durability module --- README.md | 4 + .../java/eu/m724/tweaks/TweaksPlugin.java | 3 + .../module/durability/DurabilityCaches.java | 59 +++++++ .../module/durability/DurabilityModule.java | 151 ++++++++++++++++++ src/main/resources/plugin.yml | 5 + 5 files changed, 222 insertions(+) create mode 100644 src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java create mode 100644 src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java diff --git a/README.md b/README.md index f748457..4fbf2f2 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,10 @@ Quickly kills (terminates) the server on trigger, via command or HTTP request. ### Swing through grass Self-explanatory +### Durability alert +Self-explanatory too. \ +For simplicity, there's no configuration. Control with `tweaks724.durabilityalert` + ### Utility commands - `/ping` - displays player ping P \ diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 8c6430e..7da3a4a 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -14,6 +14,7 @@ import eu.m724.tweaks.module.auth.AuthModule; import eu.m724.tweaks.module.chat.ChatModule; import eu.m724.tweaks.module.door.DoorKnockModule; import eu.m724.tweaks.module.door.DoorOpenModule; +import eu.m724.tweaks.module.durability.DurabilityModule; import eu.m724.tweaks.module.full.FullModule; import eu.m724.tweaks.module.hardcore.HardcoreModule; import eu.m724.tweaks.module.killswitch.KillswitchModule; @@ -154,6 +155,8 @@ public class TweaksPlugin extends MStatsPlugin { TweaksModule.init(SwingModule.class); } + TweaksModule.init(DurabilityModule.class); + /* end modules */ if (config.metrics()) { diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java new file mode 100644 index 0000000..4ab41d7 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java @@ -0,0 +1,59 @@ +/* + * 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.durability; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; + +public class DurabilityCaches { + private final Map lastFullReminder = new HashMap<>(); + // BAD + private final Map> lastUse = new HashMap<>(); + // BAD + private final Map> lastPing = new HashMap<>(); + + boolean shouldFullRemind(Player player, long now) { + var lfr = lastFullReminder.getOrDefault(player, 0L); + + if (now - lfr > 300 * 1000) { + lastFullReminder.put(player, now); + return true; + } else if (now - lfr < 3 * 1000) { + return true; + } + + return false; + } + + boolean shouldRemind(Player player, ItemStack itemStack, long now) { + var lu = lastUse.computeIfAbsent(player, (k) -> new HashMap<>()).getOrDefault(itemStack.getType(), 0L); + + if (now - lu > 180 * 1000) { + lastUse.get(player).put(itemStack.getType(), now); + return true; + } else if (now - lu < 3 * 1000) { + return true; + } + + return false; + } + + boolean shouldPing(Player player, ItemStack itemStack, long now) { + var lp = lastPing.computeIfAbsent(player, (k) -> new HashMap<>()).getOrDefault(itemStack.getType(), 0L); + + if (now - lp > 60 * 1000) { + lastPing.get(player).put(itemStack.getType(), now); + return true; + } + + return false; + } +} diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java new file mode 100644 index 0000000..f8bde5a --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java @@ -0,0 +1,151 @@ +/* + * 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.durability; + +import eu.m724.tweaks.DebugLogger; +import eu.m724.tweaks.module.TweaksModule; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.ComponentBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.scheduler.BukkitRunnable; + +import java.awt.Color; + +public class DurabilityModule extends TweaksModule implements Listener { + private final DurabilityCaches cache = new DurabilityCaches(); + + @Override + protected void onInit() { + registerEvents(this); + + new BukkitRunnable() { + @Override + public void run() { + Bukkit.getServer().getOnlinePlayers().forEach(p -> refreshBar(p)); + } + }.runTaskTimerAsynchronously(getPlugin(), 0, 40); + } + + @EventHandler + public void onPlayerItemDamage(PlayerItemDamageEvent event) { + refreshBar(event.getPlayer(), event.getItem(), event.getDamage()); + } + + private void refreshBar(Player player) { + refreshBar(player, null, -1); + } + + private void refreshBar(Player player, ItemStack justDamaged, int damage) { + var items = new ItemStack[] { + player.getInventory().getHelmet(), + player.getInventory().getChestplate(), + player.getInventory().getLeggings(), + player.getInventory().getBoots(), + player.getInventory().getItemInMainHand(), + player.getInventory().getItemInOffHand() + }; + + var builder = new ComponentBuilder(); + + var now = System.currentTimeMillis(); + var all = cache.shouldFullRemind(player, now); + + for (var itemStack : items) { + if (itemStack == null || !itemStack.hasItemMeta()) continue; + + if (itemStack.getItemMeta() instanceof Damageable meta) { + var target = itemStack.equals(justDamaged); + + var maxDurability = itemStack.getType().getMaxDurability(); + var durability = maxDurability - meta.getDamage() - (target ? damage : 0); + durability = Math.max(0, durability); + var percentage = (double) durability / maxDurability; + + var notify = durability < 30 && (durability < 10 || percentage < 0.1); + + var remind = cache.shouldRemind(player, itemStack, now); + var important = target && notify && cache.shouldPing(player, itemStack, now); + + DebugLogger.finer("%s's %s: %d / %d (%.2f%%)%s%s", player.getName(), itemStack.getType().name(), durability, maxDurability, percentage * 100, notify ? " notify" : "", important ? " important" : ""); + + if (notify || all || remind) { + var longName = remind || important; + var label = longName ? getMaterialLongName(itemStack.getType()) : getMaterialShortName(itemStack.getType()); + var labelColor = percentage > 0 ? matColor(itemStack.getType()) : ChatColor.DARK_RED; + + var percentageStr = (int) (percentage * 100) + "%"; + var percentageColor = mixColor(labelColor, ChatColor.DARK_RED, 1.0 - percentage * 10); + + builder.append(label + " ").color(labelColor); + builder.append(percentageStr + " ").color(percentageColor); + + if (important) { + player.playSound(player, Sound.BLOCK_ANVIL_PLACE, 0.5f, 1.5f); + player.sendTitle("", labelColor + label + " " + percentageColor + percentageStr, 5, 20, 5); + } + } + } + } + + var component = builder.create(); + if (component.length > 0) + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, component); + } + + private String getMaterialLongName(Material material) { + var sp = material.name().split("_"); + var str = sp[sp.length - 1]; + return str.charAt(0) + str.substring(1).toLowerCase(); + } + + private String getMaterialShortName(Material material) { + return getMaterialLongName(material).substring(0, 2); + } + + private ChatColor mixColor(ChatColor from, ChatColor to, double percentage) { + percentage = Math.clamp(percentage, 0.0, 1.0); + + var diffR = to.getColor().getRed() - from.getColor().getRed(); + var diffG = to.getColor().getGreen() - from.getColor().getGreen(); + var diffB = to.getColor().getBlue() - from.getColor().getBlue(); + + var r = from.getColor().getRed() + (int) (diffR * percentage); + var g = from.getColor().getGreen() + (int) (diffG * percentage); + var b = from.getColor().getBlue() + (int) (diffB * percentage); + + return ChatColor.of(new Color(r, g, b)); + } + + private ChatColor matColor(Material material) { + var color = ChatColor.DARK_GRAY; + + if (material.name().startsWith("DIAMOND_")) { + color = ChatColor.AQUA; + } else if (material.name().startsWith("NETHERITE_")) { + color = ChatColor.DARK_PURPLE; + } else if (material.name().startsWith("IRON_")) { + color = ChatColor.WHITE; + } else if (material.name().startsWith("STONE_")) { + color = ChatColor.GRAY; + } else if (material.name().startsWith("WOODEN_")) { + color = ChatColor.DARK_GREEN; + } else if (material.name().startsWith("GOLDEN_")) { + color = ChatColor.GOLD; + } + + return color; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5b193b2..5a84f24 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -40,6 +40,9 @@ commands: servkill: description: Immediately stop the server permission: tweaks724.servkill + durabilityalert: + description: Durability alert toggle + permission: tweaks724.durabilityalert permissions: tweaks724.chatmanage: @@ -58,6 +61,8 @@ permissions: default: op tweaks724.servkill: default: false + tweaks724.durabilityalert: + default: true 7weaks724.ignore.this: description: "Internal, not for use. ${project.spigot.version}" From 232e0bfa9aed45a36740bb9e5e7b180793f6f3db Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 28 Jan 2025 10:18:15 +0100 Subject: [PATCH 67/89] Durability toggle --- .../module/durability/DPlayerProperties.java | 59 +++++++++++++++++++ .../module/durability/DurabilityCommands.java | 41 +++++++++++++ .../module/durability/DurabilityModule.java | 8 ++- src/main/resources/strings.properties | 7 ++- 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java create mode 100644 src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java diff --git a/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java b/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java new file mode 100644 index 0000000..d3a92d3 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java @@ -0,0 +1,59 @@ +/* + * 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.durability; + +import eu.m724.tweaks.TweaksPlugin; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.persistence.PersistentDataType; + +import java.util.HashSet; +import java.util.Set; + +public class DPlayerProperties implements Listener { + private final NamespacedKey namespacedKey = new NamespacedKey(TweaksPlugin.getInstance(), "durability_enabled"); + private final Set players = new HashSet<>(); + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + var player = event.getPlayer(); + + if (player.hasPermission("tweaks724.durabilityalert")) { + var enabled = player.getPersistentDataContainer().get(namespacedKey, PersistentDataType.BOOLEAN); + if (enabled != null && enabled) { + players.add(player); + } + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + players.remove(event.getPlayer()); + } + + Set getPlayers() { + return Set.copyOf(players); + } + + boolean isPlayerEnabled(Player player) { + return players.contains(player); + } + + void disableForPlayer(Player player) { + players.remove(player); + player.getPersistentDataContainer().set(namespacedKey, PersistentDataType.BOOLEAN, false); + } + + void enableForPlayer(Player player) { + players.add(player); + player.getPersistentDataContainer().set(namespacedKey, PersistentDataType.BOOLEAN, true); + } +} diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java new file mode 100644 index 0000000..2d6501c --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java @@ -0,0 +1,41 @@ +/* + * 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.durability; + +import eu.m724.tweaks.Language; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class DurabilityCommands implements CommandExecutor { + private final DPlayerProperties properties; + + public DurabilityCommands(DPlayerProperties properties) { + this.properties = properties; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage("Only players can use this command"); + return true; + } + + if (properties.isPlayerEnabled(player)) { + properties.disableForPlayer(player); + sender.spigot().sendMessage(Language.getComponent("durabilityDisabled", ChatColor.GRAY)); + } else { + properties.enableForPlayer(player); + sender.spigot().sendMessage(Language.getComponent("durabilityEnabled", ChatColor.GRAY)); + } + + return true; + } +} diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java index f8bde5a..b582bfc 100644 --- a/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java +++ b/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java @@ -11,7 +11,6 @@ import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.ComponentBuilder; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -26,15 +25,18 @@ import java.awt.Color; public class DurabilityModule extends TweaksModule implements Listener { private final DurabilityCaches cache = new DurabilityCaches(); + private final DPlayerProperties properties = new DPlayerProperties(); @Override protected void onInit() { registerEvents(this); + registerCommand("durabilityalert", new DurabilityCommands(properties)); + new BukkitRunnable() { @Override public void run() { - Bukkit.getServer().getOnlinePlayers().forEach(p -> refreshBar(p)); + properties.getPlayers().forEach(p -> refreshBar(p)); } }.runTaskTimerAsynchronously(getPlugin(), 0, 40); } @@ -49,6 +51,8 @@ public class DurabilityModule extends TweaksModule implements Listener { } private void refreshBar(Player player, ItemStack justDamaged, int damage) { + if (!properties.isPlayerEnabled(player)) return; + var items = new ItemStack[] { player.getInventory().getHelmet(), player.getInventory().getChestplate(), diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 550c4f8..9394be9 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -1,5 +1,5 @@ # -# Copyright (C) 2024 Minecon724 +# 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. # @@ -32,4 +32,7 @@ authKickUnregistered = You are not whitelisted on this server! redstoneGatewayItem = Redstone gateway -clickToCopy = Click to copy to clipboard \ No newline at end of file +clickToCopy = Click to copy to clipboard + +durabilityEnabled = Enabled durability alert +durabilityDisabled = Disabled durability alert \ No newline at end of file From c096674a15f4a0ff41151c92832c63503dd75aab Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 2 Feb 2025 14:03:22 +0100 Subject: [PATCH 68/89] Support sleep mechanics across multiple worlds Refactored `TimeForwardRunnable` to handle multiple worlds instead of a single hardcoded world. The code now dynamically retrieves sleep percentage and processes time advancement for each world, improving flexibility and compatibility. --- .../module/sleep/TimeForwardRunnable.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java b/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java index 80b6f3e..d435be9 100644 --- a/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java @@ -14,37 +14,38 @@ import org.bukkit.scheduler.BukkitRunnable; public class TimeForwardRunnable extends BukkitRunnable { private final Server server; - private final World world; // TODO multi worlds - - private final double percentage; public TimeForwardRunnable(Plugin plugin) { this.server = plugin.getServer(); - this.world = server.getWorld("world"); - this.percentage = (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0); } @Override public void run() { - int playersSleeping = SleepState.playersSleeping; - //System.out.println(playersSleeping); - if (playersSleeping == 0) return; + for (World world : server.getWorlds()) { + var gameRuleValue = world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE); + if (gameRuleValue == null) gameRuleValue = 100; + double percentage = gameRuleValue / 100.0; - int onlinePlayers = (int) (server.getOnlinePlayers().size() / percentage); // TODO optimize remove size every tick maybe + int playersSleeping = SleepState.playersSleeping; + //System.out.println(playersSleeping); + if (playersSleeping == 0) return; - double sleepPercentage = (double) playersSleeping / onlinePlayers; + int onlinePlayers = (int) (world.getPlayers().size() / percentage); - // we want sleep to take 200 ticks which is 10 seconds assuming all palyres onilien + double sleepPercentage = (double) playersSleeping / onlinePlayers; - long time = world.getTime(); - long untilDay = 23459 - time; + // we want sleep to take 200 ticks which is 10 seconds assuming all palyres onilien - if (untilDay == 0) return; + long time = world.getTime(); + long untilDay = 23459 - time; - long perSkip = 200 + (100000 / -untilDay); - perSkip = Math.clamp(perSkip, 20, 200); - perSkip = (long) (perSkip * sleepPercentage); + if (untilDay == 0) return; - world.setTime(world.getTime() + perSkip); + long perSkip = 200 + (100000 / -untilDay); + perSkip = Math.clamp(perSkip, 20, 200); + perSkip = (long) (perSkip * sleepPercentage); + + world.setTime(world.getTime() + perSkip); + } } } From cbe9f77cca06fa1d7f17d64361fa469d81adfa97 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 2 Feb 2025 14:05:44 +0100 Subject: [PATCH 69/89] Remove obsolete comment about static method in TweaksModule The removed comment questioned making a method non-static, which is already resolved or irrelevant. This cleanup improves code readability and eliminates confusion. --- src/main/java/eu/m724/tweaks/module/TweaksModule.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/module/TweaksModule.java b/src/main/java/eu/m724/tweaks/module/TweaksModule.java index e3f4de0..f554a8e 100644 --- a/src/main/java/eu/m724/tweaks/module/TweaksModule.java +++ b/src/main/java/eu/m724/tweaks/module/TweaksModule.java @@ -34,7 +34,6 @@ public abstract class TweaksModule { DebugLogger.fine("Initialized %s in %d µs", name, (end - start) / 1000); } - // TODO not static maybe? protected TweaksPlugin getPlugin() { return TweaksPlugin.getInstance(); } From 7de46b879bb07fcdeea02240afa70d3adbd4b6d4 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 2 Feb 2025 14:12:19 +0100 Subject: [PATCH 70/89] Refactor MOTD configuration and improve file handling Revised the MOTD configuration setup to use a direct boolean flag for enabling/disabling instead of relying on string checks. Updated file handling to use `Path` and modernized directory creation logic for better error handling and clarity. Removed unused code and cleaned up resource management in `MotdModule`. --- .../eu/m724/tweaks/config/ConfigLoader.java | 2 +- .../m724/tweaks/module/motd/MotdModule.java | 29 +++++++++---------- src/main/resources/config.yml | 2 +- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/config/ConfigLoader.java b/src/main/java/eu/m724/tweaks/config/ConfigLoader.java index 36d7cd4..cf725f9 100644 --- a/src/main/java/eu/m724/tweaks/config/ConfigLoader.java +++ b/src/main/java/eu/m724/tweaks/config/ConfigLoader.java @@ -41,8 +41,8 @@ class ConfigLoader { boolean doorDoubleOpen = getBoolean("doors.doubleOpen"); boolean doorKnocking = getBoolean("doors.knocking"); + boolean motdEnabled = getBoolean("motd.enabled"); String motdSet = getString("motd.set"); - boolean motdEnabled = !(motdSet.equals("false") || motdSet.isBlank()); boolean chatEnabled = getBoolean("chat.enabled"); boolean chatLocalEvents = getBoolean("chat.localEvents"); diff --git a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java index b0534cd..4962f02 100644 --- a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java +++ b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java @@ -13,7 +13,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import eu.m724.tweaks.DebugLogger; -import eu.m724.tweaks.config.TweaksConfig; import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; @@ -22,44 +21,42 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.status.ServerStatus; -import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; public class MotdModule extends TweaksModule { - private Component[] motds; - @Override protected void onInit() { - // TODO adding more MOTD features would require checking whether to enable set - - String motdSetName = TweaksConfig.getConfig().motdSet(); - String motdSetPath = "motd sets/" + motdSetName + ".txt"; - File motdSetsFile = new File(getPlugin().getDataFolder(), motdSetPath); + Path motdSetPath = getPlugin().getDataFolder().toPath().resolve("motd sets").resolve(getConfig().motdSet() + ".txt"); // create "motd sets" directory - motdSetsFile.getParentFile().mkdirs(); + try { + Files.createDirectories(motdSetPath); + } catch (IOException e) { + throw new RuntimeException(e); + } // if this is a builtin set - if (!motdSetsFile.exists() && getPlugin().hasResource(motdSetPath)) - getPlugin().saveResource(motdSetPath, false); + if (!Files.exists(motdSetPath) && getPlugin().hasResource("motd sets/" + motdSetPath.getFileName())) + getPlugin().saveResource("motd sets/" + motdSetPath.getFileName(), false); - if (!motdSetsFile.exists()) { - throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(motdSetName)); + if (!Files.exists(motdSetPath)) { + throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(getConfig().motdSet())); } String fileContent; try { - fileContent = Files.readString(motdSetsFile.toPath()); + fileContent = Files.readString(motdSetPath); } catch (IOException e) { throw new RuntimeException("Reading motd set", e); } // MOTDs are split with an empty line - motds = Arrays.stream(fileContent.split("\n\n")) + Component[] motds = Arrays.stream(fileContent.split("\n\n")) .map(entry -> { entry = entry.strip(); JsonElement json = null; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5083716..6b48d5f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -36,9 +36,9 @@ doors: knocking: true motd: + enabled: true # Name of the set containing the MOTDs # (random displayed every ping) - # "" or false to disable set: "example" chat: From ad1a699d388dbc40fe00c5026abbdacee60a422d Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 2 Feb 2025 14:57:00 +0100 Subject: [PATCH 71/89] feat(auth): improve error handling and key generation logic Added new error handling for key assignment failures, including user-facing messaging. Enhanced secure key generation with fixed length and randomness via `SecureRandom`. Removed redundant TODO comments and replaced placeholder exception handling with actionable implementations. --- .../m724/tweaks/module/auth/AuthListener.java | 6 ++++ .../m724/tweaks/module/auth/AuthStorage.java | 30 ++++++++----------- src/main/resources/strings.properties | 1 + 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java index bc4634c..b22b677 100644 --- a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.module.auth; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; import eu.m724.tweaks.config.TweaksConfig; import org.bukkit.entity.Player; @@ -14,6 +15,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerLoginEvent; import java.io.FileNotFoundException; +import java.io.IOException; public class AuthListener implements Listener { private final AuthStorage authStorage; @@ -40,6 +42,10 @@ public class AuthListener implements Listener { allowed = true; // key just assigned } catch (FileNotFoundException | AuthStorage.AlreadyClaimedException | AuthStorage.InvalidKeyException e) { allowed = !force; // If forced all players must have a key + } catch (IOException e) { + DebugLogger.severe("Error assigning key to player. " + e.getMessage()); + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, Language.getString("authKickError")); + allowed = true; // to skip the below checks } } diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java b/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java index 7eb9c64..6692723 100644 --- a/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java +++ b/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java @@ -11,10 +11,15 @@ import org.bukkit.plugin.Plugin; import java.io.*; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; import java.util.Random; import java.util.UUID; public class AuthStorage { + private static final char[] KEY_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); + private static final int KEY_LENGTH = 10; + private static final SecureRandom RANDOM = new SecureRandom(); + private final File playersDirectory; private final File keysDirectory; @@ -71,7 +76,7 @@ public class AuthStorage { byte[] bytes = is.readNBytes(50); return new String(bytes, StandardCharsets.UTF_8); } catch (IOException e) { - throw new RuntimeException(e); // TODO + throw new RuntimeException(e); } } @@ -121,7 +126,7 @@ public class AuthStorage { * @throws FileNotFoundException if no such key * @throws AlreadyClaimedException if key is claimed or user owns another key */ - void assignOwner(String key, UUID uuid) throws FileNotFoundException, AlreadyClaimedException { + void assignOwner(String key, UUID uuid) throws IOException, FileNotFoundException, AlreadyClaimedException { if (isInvalid(key)) throw new InvalidKeyException(); if (getUserOfKey(key) != null) throw new AlreadyClaimedException(); @@ -136,34 +141,25 @@ public class AuthStorage { try (FileOutputStream os = new FileOutputStream(file)) { os.write(byteBuffer.array()); - } catch (IOException e) { - throw new RuntimeException(e); // TODO } File file2 = new File(playersDirectory, uuid.toString()); try (FileOutputStream os = new FileOutputStream(file2)) { os.write(key.getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - throw new RuntimeException(e); // TODO } } - // TODO improve String generateKey() { - char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray(); - Random random = new Random(); - int length = random.nextInt(8, 10); + StringBuilder builder = new StringBuilder(); - StringBuilder key = new StringBuilder(); - - for (int i=0; i Date: Sun, 2 Feb 2025 14:57:18 +0100 Subject: [PATCH 72/89] refactor(pomodoro): simplify plugin instance retrieval Replaced passing the plugin instance to PomodoroRunnable with direct access via TweaksPlugin singleton. This removes redundant code, improving clarity and maintainability. --- .../eu/m724/tweaks/module/pomodoro/PomodoroModule.java | 2 +- .../eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java index 74cdedf..89dd3d5 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java @@ -12,7 +12,7 @@ public class PomodoroModule extends TweaksModule { @Override protected void onInit() { registerEvents(new PomodoroListener()); - new PomodoroRunnable(getPlugin()).runTaskTimerAsynchronously(getPlugin(), 0, 20L); + new PomodoroRunnable().runTaskTimerAsynchronously(getPlugin(), 0, 20L); registerCommand("pomodoro", new PomodoroCommands()); } diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java index 6612d6d..1b70d5f 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.module.pomodoro; +import eu.m724.tweaks.TweaksPlugin; import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; @@ -15,15 +16,12 @@ import org.bukkit.scheduler.BukkitRunnable; public class PomodoroRunnable extends BukkitRunnable { private final boolean force = TweaksConfig.getConfig().pomodoroForce(); - private final Plugin plugin; - - public PomodoroRunnable(Plugin plugin) { - this.plugin = plugin; // only used for kicking - } + private final Plugin plugin = TweaksPlugin.getInstance(); // used only to kick @Override public void run() { long now = System.nanoTime(); + Bukkit.getOnlinePlayers().forEach(player -> { PlayerPomodoro pomodoro = Pomodoros.get(player); if (pomodoro == null) return; From 541f095075a4eb600decd62e0d660a73c6c51cb4 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 10:42:12 +0100 Subject: [PATCH 73/89] fix(motd): handle FileAlreadyExistsException in directory creation Added a catch block for FileAlreadyExistsException to prevent unnecessary exceptions when the "motd sets" directory already exists. This ensures smoother execution and improves error handling during initialization. Signed-off-by: Minecon724 --- src/main/java/eu/m724/tweaks/module/motd/MotdModule.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java index 4962f02..63f1b6c 100644 --- a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java +++ b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java @@ -7,7 +7,8 @@ package eu.m724.tweaks.module.motd; import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.*; +import com.comphenix.protocol.events.InternalStructure; +import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.reflect.StructureModifier; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; @@ -22,6 +23,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.status.ServerStatus; import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -36,6 +38,8 @@ public class MotdModule extends TweaksModule { // create "motd sets" directory try { Files.createDirectories(motdSetPath); + } catch (FileAlreadyExistsException ignored) { + } catch (IOException e) { throw new RuntimeException(e); } From 6ff6ec9d6b21f3900ca7d9a2e091a870574b5c04 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 10:52:04 +0100 Subject: [PATCH 74/89] fix: improve error handling in ChatCommands Updated error handling to throw RuntimeException instead of printing stack traces. Enhanced user feedback by standardizing error messages across various chat command operations. Signed-off-by: Minecon724 --- .../eu/m724/tweaks/module/chat/ChatCommands.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java index d6fa1ba..a9f6f50 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java @@ -99,8 +99,8 @@ public class ChatCommands implements CommandExecutor { } catch (ChatModule.ChatRoomExistsException e) { sender.sendMessage("Room %s already exists".formatted(argument)); } catch (IOException e) { - sender.sendMessage("Failed to create room"); - e.printStackTrace(); + sender.sendMessage("Error creating room"); + throw new RuntimeException(e); } } case "delete" -> { @@ -124,8 +124,8 @@ public class ChatCommands implements CommandExecutor { manager.saveChatRoom(chatRoom); sender.sendMessage("Owner changed to " + newOwner.getName()); } catch (IOException e) { - sender.sendMessage("Failed to change owner"); - e.printStackTrace(); + sender.sendMessage("Error changing owner"); + throw new RuntimeException(e); } } else { sender.sendMessage("Player must be online"); @@ -141,8 +141,8 @@ public class ChatCommands implements CommandExecutor { manager.saveChatRoom(chatRoom); sender.sendMessage("Password changed"); } catch (IOException e) { - sender.sendMessage("Failed to change password"); - e.printStackTrace(); + sender.sendMessage("Error changing password"); + throw new RuntimeException(e); } } else { sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); @@ -157,8 +157,8 @@ public class ChatCommands implements CommandExecutor { manager.saveChatRoom(chatRoom); sender.sendMessage("Message color changed to " + newColor.getName()); } catch (IOException e) { - sender.sendMessage("Failed to change color"); - e.printStackTrace(); + sender.sendMessage("Error changing color"); + throw new RuntimeException(e); } } else { sender.sendMessage("Invalid color"); From 316d479fd8a02424b87dc3fbcbdbfc23ea7cb49f Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 11:25:26 +0100 Subject: [PATCH 75/89] feat(chat): improve chat room management UX - Added hover and click actions to chat commands for better interaction. - Enhanced error and confirmation messages for clarity. - Introduced validation for room IDs and improved handling of invalid IDs. Signed-off-by: Minecon724 --- .../m724/tweaks/module/chat/ChatCommands.java | 219 +++++++++++------- .../m724/tweaks/module/chat/ChatModule.java | 6 +- .../tweaks/module/chat/ChatRoomLoader.java | 5 +- src/main/resources/strings.properties | 12 +- 4 files changed, 148 insertions(+), 94 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java index a9f6f50..59133f0 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java @@ -9,6 +9,10 @@ package eu.m724.tweaks.module.chat; import eu.m724.tweaks.Language; 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.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -64,7 +68,11 @@ public class ChatCommands implements CommandExecutor { authenticated = true; } } else { - component = Language.getComponent("chatNoSuchRoom", ChatColor.RED, id); + if (ChatRoomLoader.validateId(id) == 0) { + component = Language.getComponent("chatNoSuchRoom", ChatColor.RED, id); + } else { + component = Language.getComponent("chatNoSuchRoomInvalidId", ChatColor.RED, id); + } } if (authenticated) { @@ -84,110 +92,153 @@ public class ChatCommands implements CommandExecutor { ChatRoom chatRoom = manager.getPlayerChatRoom(player); boolean isOwner = player.equals(chatRoom.owner); - if (args.length > 1) { - String action = args[0]; - String argument = args[1]; + String action = args.length > 0 ? args[0] : null; + String argument = args.length > 1 ? args[1] : null; - switch (action) { - case "create" -> { - try { - ChatRoom newRoom = manager.createChatRoom(argument, null, player); - sender.sendMessage("Created a chat room. Join it: /c " + newRoom.id); - sender.sendMessage("You might also want to protect it with a password: /cm setpassword"); - } catch (ChatModule.InvalidIdException e) { - sender.sendMessage("ID is invalid: " + e.getMessage()); - } catch (ChatModule.ChatRoomExistsException e) { - sender.sendMessage("Room %s already exists".formatted(argument)); - } catch (IOException e) { - sender.sendMessage("Error creating room"); - throw new RuntimeException(e); - } + switch (action) { + case "create" -> { + if (argument == null) { + sender.sendMessage("Please pass a room name as an argument. The room name can contain only characters and digits."); + return true; } - case "delete" -> { + + try { + ChatRoom newRoom = manager.createChatRoom(argument, null, player); + + var component = new ComponentBuilder("Created a chat room. Join it: ").color(ChatColor.GOLD) + .append("/c " + newRoom.id).color(ChatColor.AQUA) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/c " + newRoom.id)) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand")))) + .append("\n") + .append("To protect it with a password, join it and use ").color(ChatColor.GRAY) + .append("/cm setpassword ").color(ChatColor.DARK_PURPLE) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/cm setpassword ")) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand")))); + + sender.spigot().sendMessage(component.build()); + } catch (ChatModule.InvalidIdException e) { + var component = new ComponentBuilder("ID is invalid: ").color(ChatColor.GRAY) + .append(e.getMessage()).color(ChatColor.RED); + + sender.spigot().sendMessage(component.build()); + } catch (ChatModule.ChatRoomExistsException e) { + sender.sendMessage("Room %s already exists".formatted(argument)); + } catch (IOException e) { + sender.sendMessage("Error creating room"); + throw new RuntimeException(e); + } + } + case "delete" -> { + if (isOwner) { + if (argument == null) { + sender.sendMessage("You want to delete room \"%s\". Confirm by passing the ID as an argument.".formatted(chatRoom.id)); + return true; + } + if (argument.equals(chatRoom.id)) { - if (isOwner) { - manager.deleteChatRoom(chatRoom); - sender.sendMessage("Room %s deleted".formatted(chatRoom.id)); - } else { - sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); - } + manager.deleteChatRoom(chatRoom); + sender.sendMessage("Room %s deleted".formatted(chatRoom.id)); } else { - sender.sendMessage("Pass %s as an argument to confirm".formatted(chatRoom.id)); + sender.sendMessage("Pass \"%s\" as an argument to confirm".formatted(chatRoom.id)); } + } else { + sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); } - case "setowner" -> { - if (isOwner) { - Player newOwner = Bukkit.getPlayer(argument); - if (newOwner != null && newOwner.isOnline()) { - chatRoom.owner = newOwner; - try { - manager.saveChatRoom(chatRoom); - sender.sendMessage("Owner changed to " + newOwner.getName()); - } catch (IOException e) { - sender.sendMessage("Error changing owner"); - throw new RuntimeException(e); - } - } else { - sender.sendMessage("Player must be online"); - } - } else { - sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); + } + case "setowner" -> { + if (isOwner) { + if (argument == null) { + sender.sendMessage("To transfer ownership of room %s, pass the new owner name as an argument for this action.".formatted(chatRoom.id)); + return true; } - } - case "setpassword" -> { - if (isOwner) { - chatRoom.password = Arrays.stream(args).skip(1).collect(Collectors.joining(" ")); + + Player newOwner = Bukkit.getPlayer(argument); + if (newOwner != null && newOwner.isOnline()) { + chatRoom.owner = newOwner; try { manager.saveChatRoom(chatRoom); - sender.sendMessage("Password changed"); + sender.sendMessage("Owner changed to " + newOwner.getName()); } catch (IOException e) { - sender.sendMessage("Error changing password"); + sender.sendMessage("Error changing owner"); throw new RuntimeException(e); } } else { - sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); + sender.sendMessage("Player must be online"); } + } else { + sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); } - case "setcolor" -> { - if (isOwner) { - ChatColor newColor = ChatColor.of(argument); - if (newColor != null) { - chatRoom.color = newColor; - try { - manager.saveChatRoom(chatRoom); - sender.sendMessage("Message color changed to " + newColor.getName()); - } catch (IOException e) { - sender.sendMessage("Error changing color"); - throw new RuntimeException(e); - } - } else { - sender.sendMessage("Invalid color"); + } + case "setpassword" -> { + if (isOwner) { + if (argument == null) { + sender.sendMessage("To change the password of room %s, pass the new password as an argument for this action.".formatted(chatRoom.id)); + return true; + } + + chatRoom.password = Arrays.stream(args).skip(1).collect(Collectors.joining(" ")); + try { + manager.saveChatRoom(chatRoom); + + var component = new ComponentBuilder("Password changed to ").color(ChatColor.GREEN) + .append("(hover to view)").color(ChatColor.AQUA) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(chatRoom.password))) + .append("\n") + .append("To unset, ").color(ChatColor.GRAY) + .append("/cm unsetpassword").color(ChatColor.DARK_PURPLE) + .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/cm unsetpassword")) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand")))); + + sender.spigot().sendMessage(component.build()); + } catch (IOException e) { + sender.sendMessage("Error changing password"); + throw new RuntimeException(e); + } + } else { + sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); + } + } + case "unsetpassword" -> { + if (isOwner) { + chatRoom.password = null; + try { + manager.saveChatRoom(chatRoom); + sender.sendMessage("Password removed from " + chatRoom.id); + } catch (IOException e) { + sender.sendMessage("Error removing password"); + throw new RuntimeException(e); + } + } else { + sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); + } + } + case "setcolor" -> { + if (isOwner) { + if (argument == null) { + sender.sendMessage("To change the message color of room %s, pass the new color as an argument for this action. #hex or color name.".formatted(chatRoom.id)); + return true; + } + + ChatColor newColor = ChatColor.of(argument); + if (newColor != null) { + chatRoom.color = newColor; + try { + manager.saveChatRoom(chatRoom); + sender.sendMessage("Message color changed to " + newColor.getName()); + } catch (IOException e) { + sender.sendMessage("Error changing color"); + throw new RuntimeException(e); } } else { - sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); + sender.sendMessage("Invalid color"); } - } - default -> { - sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor"); + } else { + sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id)); } } - } else if (args.length > 0) { - switch (args[0]) { - case "create" -> - sender.sendMessage("Please pass a room name as an argument. The room name must be of characters and digits."); - case "delete" -> - sender.sendMessage("You want to delete room %s. Confirm by passing its name as an argument for this action.".formatted(chatRoom.id)); - case "setowner" -> - sender.sendMessage("To transfer ownership of room %s, pass the new owner name as an argument for this action.".formatted(chatRoom.id)); - case "setpassword" -> - sender.sendMessage("To change the password of room %s, pass the new password as an argument for this action.".formatted(chatRoom.id)); - case "setcolor" -> - sender.sendMessage("To change the message color of room %s, pass the new color as an argument for this action. #hex or color name.".formatted(chatRoom.id)); - default -> - sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor"); + case null, default -> { + sender.sendMessage("Actions: create, delete, setowner, setpassword, unsetpassword, setcolor"); } - } else { - sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor"); } } diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java index 74f823d..dcd8bf2 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java @@ -153,11 +153,11 @@ public class ChatModule extends TweaksModule { case 0: break; case 1: - throw new InvalidIdException("ID is too short, make it at least 2 chars"); + throw new InvalidIdException("ID is too short, it must be at least 2 chars long"); case 2: - throw new InvalidIdException("ID is too long, make it 20 chars or shorter"); + throw new InvalidIdException("ID is too long, it mustn't be longer than 20 chars"); case 4: - throw new InvalidIdException("ID must be composed from characters a-z and numbers 0-9"); + throw new InvalidIdException("ID must be of characters a-z and numbers 0-9"); } if (getById(id) != null) diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java b/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java index 28425d5..0af0f59 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java @@ -29,7 +29,7 @@ public class ChatRoomLoader { */ static File getFile(String id) { if (validateId(id) != 0) - throw new RuntimeException("Invalid id: " + id); + return null; return new File(chatRoomsDir, id + ".yml"); } @@ -66,7 +66,8 @@ public class ChatRoomLoader { */ static ChatRoom load(String id) { File chatRoomFile = getFile(id); - if (!chatRoomFile.exists()) return null; + if (chatRoomFile == null || !chatRoomFile.exists()) + return null; YamlConfiguration configuration = YamlConfiguration.loadConfiguration(chatRoomFile); diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index ccef38a..be9800a 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -13,17 +13,18 @@ languageEnglish = English updateAvailableNotice = Available updates (%d): # Used in /updates -updatesNotChecked = Not checked yet +updatesNotChecked = Not checked yet. # %s is time as HH:mm updatesNoUpdates = No available updates. Last checked: %s # %s is update title updatesClickToOpen = Click to open on SpigotMC "%s" # Used in /chat -chatPasswordProtected = This room is password protected -chatWrongPassword = Wrong password -chatNoSuchRoom = No room named %s -chatAlreadyHere = You're already in this room +chatPasswordProtected = This room is password protected. +chatWrongPassword = Wrong password. +chatNoSuchRoom = Room %s doesn't exist. +chatNoSuchRoomInvalidId = Room %s doesn't exist, because the ID is invalid. +chatAlreadyHere = You're already in this room. # Used when a player joins using the wrong key or no key authKickWrongKey = You're connecting to the wrong server address. You must connect to the one you're registered to. @@ -34,6 +35,7 @@ authKickError = An error occured. Please try again. If this persists, contact an redstoneGatewayItem = Redstone gateway clickToCopy = Click to copy to clipboard +clickToExecuteCommand = Click to execute command durabilityEnabled = Enabled durability alert durabilityDisabled = Disabled durability alert \ No newline at end of file From 05b9ca4cb8517d11cb6d5dbe56367d2092030a85 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 11:27:21 +0100 Subject: [PATCH 76/89] feat(chat): initialize ChatRoomLoader on plugin start - Added ChatRoomLoader initialization during ChatModule setup. - Ensures necessary resources are loaded before chat operations. Signed-off-by: Minecon724 --- src/main/java/eu/m724/tweaks/module/chat/ChatModule.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java index dcd8bf2..ad8ae65 100644 --- a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java +++ b/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java @@ -32,12 +32,14 @@ public class ChatModule extends TweaksModule { throw new RuntimeException("Please disable enforce-secure-profile in server.properties to use chatrooms"); } + ChatRoomLoader.init(getPlugin()); getById(defaultRoom); registerEvents(new ChatListener(this)); var chatCommands = new ChatCommands(this); registerCommand("chat", chatCommands); registerCommand("chatmanage", chatCommands); + } /** From 0c4690e2e77fbb69c802ccab915402880f443aef Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 11:27:34 +0100 Subject: [PATCH 77/89] [maven-release-plugin] prepare release tweaks-0.1.14 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9663441..22761da 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.14-SNAPSHOT + 0.1.14 21 @@ -168,6 +168,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - HEAD + tweaks-0.1.14 \ No newline at end of file From cf654fcb4255bc0d6392c6700c16508ad2a44b51 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 3 Feb 2025 11:27:37 +0100 Subject: [PATCH 78/89] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 22761da..f7baa10 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ eu.m724 tweaks - 0.1.14 + 0.1.15-SNAPSHOT 21 @@ -168,6 +168,6 @@ scm:git:git@git.m724.eu:Minecon724/tweaks724.git - tweaks-0.1.14 + HEAD \ No newline at end of file From 684e31bf078074bf2d0868239fa037912beab2d6 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 4 Feb 2025 17:20:45 +0100 Subject: [PATCH 79/89] fix: correct string formatting in debug logger Updated the debug logger to use proper string formatting syntax. This ensures compatibility and avoids runtime errors. Signed-off-by: Minecon724 --- src/main/java/eu/m724/tweaks/TweaksPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 7da3a4a..2b0715c 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -164,7 +164,7 @@ public class TweaksPlugin extends MStatsPlugin { mStats(1); } - DebugLogger.fine("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0)); + DebugLogger.fine("Took %.3f milliseconds", (System.nanoTime() - start) / 1000000.0); } private String getTargetVersion() { From b421b48e51da7960ffedcddfc0b6cd3e4c4a8ffb Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Mon, 17 Feb 2025 09:06:39 +0100 Subject: [PATCH 80/89] chore: Update mStats to fix am issue Signed-off-by: Minecon724 --- pom.xml | 2 +- src/main/resources/plugin.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f7baa10..7c04e18 100644 --- a/pom.xml +++ b/pom.xml @@ -147,7 +147,7 @@ eu.m724 mstats-spigot - 0.1.0 + 0.1.2 provided diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5a84f24..18bb896 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.0 + - eu.m724:mstats-spigot:0.1.2 commands: chat: From 7cd334f4a20390d2d58b3da62c6f0c867fdad7c6 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 18 Feb 2025 14:09:19 +0100 Subject: [PATCH 81/89] feat: Initial word coords module Signed-off-by: Minecon724 --- .../java/eu/m724/tweaks/TweaksPlugin.java | 3 + .../wordcoords/WordCoordsConverter.java | 36 ++++++ .../module/wordcoords/WordCoordsModule.java | 118 ++++++++++++++++++ .../tweaks/module/wordcoords/WordList.java | 63 ++++++++++ .../module/wordcoords/converter/Decoder.java | 76 +++++++++++ .../module/wordcoords/converter/Encoder.java | 82 ++++++++++++ src/main/resources/plugin.yml | 6 + src/main/resources/strings.properties | 6 +- 8 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/WordList.java create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java index 2b0715c..82adee7 100644 --- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java +++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java @@ -27,6 +27,7 @@ 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; @@ -157,6 +158,8 @@ public class TweaksPlugin extends MStatsPlugin { TweaksModule.init(DurabilityModule.class); + TweaksModule.init(WordCoordsModule.class); + /* end modules */ if (config.metrics()) { diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java new file mode 100644 index 0000000..054d1ee --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java @@ -0,0 +1,36 @@ +/* + * 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 new file mode 100644 index 0000000..de442aa --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java @@ -0,0 +1,118 @@ +/* + * 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 org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class WordCoordsModule extends TweaksModule implements CommandExecutor { + 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); + } + + @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) { + String strArgs = String.join(" ", args); + words = smartDetectWords(strArgs); + } + } + + if (encode) { + words = converter.encode(x, z); + + sender.sendMessage("%d, %d encodes to ///%s".formatted(x, z, String.join(".", words))); + } else { + int[] xz = converter.decode(words); + x = xz[0]; + z = xz[1]; + + sender.sendMessage("///%s decodes to around %d, %d".formatted(String.join(".", words), x, z)); + } + + 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 new file mode 100644 index 0000000..1b74720 --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java @@ -0,0 +1,76 @@ +/* + * 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; + +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>= bitsPerWord; + + return combinedValue; + } + + private int[] decodeCoords(long combinedValue, int bitsRequiredPerCoordinate) { + int coordinateMask = (1 << bitsRequiredPerCoordinate) - 1; + int coordinateOffset = 1 << (bitsRequiredPerCoordinate - 1); + + int z = (int) (combinedValue & coordinateMask) - coordinateOffset; + int x = (int) (combinedValue >> 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 new file mode 100644 index 0000000..caff8ac --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java @@ -0,0 +1,82 @@ +/* + * 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; + +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) { + xCoord = Math.floorDiv(xCoord, 16); + zCoord = Math.floorDiv(zCoord, 16); + DebugLogger.finer("Chunk: %d, %d", xCoord, zCoord); + + + int wordsRequired = findWordsRequired(xCoord, zCoord); + DebugLogger.finer("Words required: %d", wordsRequired); + + int bitsRequired = wordsRequired * bitsPerWord; + int bitsRequiredPerCoordinate = bitsRequired / 2; + DebugLogger.finer("Bits required: %d (per coord: %d)", bitsRequired, bitsRequiredPerCoordinate); + + + int encodedX = encodeCoord(xCoord, bitsRequiredPerCoordinate); + int encodedZ = encodeCoord(zCoord, 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); + return wordList.getWords(wordIndexes); + } + + private int findBitsRequiredPerCoordinate(int x, int z) { + int n = Math.max(Math.abs(x), Math.abs(z)); + return n == 0 ? 1 : 32 - Integer.numberOfLeadingZeros(n); + } + + private int findWordsRequired(int x, int z) { + int brpc = findBitsRequiredPerCoordinate(x, z); + return Math.ceilDiv(brpc * 2, wordList.getBitsPerWord()); + } + + 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 18bb896..40473fb 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -43,6 +43,10 @@ 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: @@ -63,6 +67,8 @@ 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 be9800a..e9dda4d 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -38,4 +38,8 @@ clickToCopy = Click to copy to clipboard clickToExecuteCommand = Click to execute command durabilityEnabled = Enabled durability alert -durabilityDisabled = Disabled durability alert \ No newline at end of file +durabilityDisabled = Disabled durability alert + +# When console executes /wordcoords without arguments +wordCoordsPlayerOnly = Only players can execute this command without arguments. +wordCoordsOutOfRange = Those coordinates are invalid. \ No newline at end of file From 598902ef3351310fbf119669ca4e599835497e79 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 19 Feb 2025 11:24:22 +0100 Subject: [PATCH 82/89] update readme Signed-off-by: Minecon724 --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4fbf2f2..3f18c19 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,14 @@ Quickly kills (terminates) the server on trigger, via command or HTTP request. Self-explanatory ### Durability alert -Self-explanatory too. \ -For simplicity, there's no configuration. Control with `tweaks724.durabilityalert` +Self-explanatory too. + +`/durabilityalert` (`tweaks724.durabilityalert`) + +### Word coords +Convert coordinates to easier to remember words + +`/wordcoords` (`tweaks724.tauth`) ### Utility commands From 22bb2d16d229f6d6ea41f16820d59bae9b1ab790 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 6 Apr 2025 10:25:18 +0200 Subject: [PATCH 83/89] Fix encoding and decoding --- .../module/wordcoords/converter/Decoder.java | 20 +++-- .../module/wordcoords/converter/Encoder.java | 90 ++++++++++++++----- 2 files changed, 83 insertions(+), 27 deletions(-) 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 index 1b74720..65ff762 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java @@ -10,6 +10,7 @@ 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; @@ -33,6 +34,8 @@ public class Decoder { } public int[] decode(int[] wordIndexes) { + DebugLogger.finer("Decoding word indexes: %s", Arrays.toString(wordIndexes)); + int bitsRequired = wordIndexes.length * wordList.getBitsPerWord(); int bitsRequiredPerCoordinate = bitsRequired / 2; DebugLogger.finer("Bits required: %d (per coord: %d)", bitsRequired, bitsRequiredPerCoordinate); @@ -43,23 +46,26 @@ public class Decoder { int[] decodedCoords = decodeCoords(combinedValue, bitsRequiredPerCoordinate); - int xCoord = decodedCoords[0]; - int zCoord = decodedCoords[1]; - DebugLogger.info("Chunk: %d, %d", xCoord, zCoord); + int chunkX = decodedCoords[0]; + int chunkZ = decodedCoords[1]; + DebugLogger.finer("Chunk: %d, %d", chunkX, chunkZ); - return new int[] { xCoord * 16 + 8, zCoord * 16 + 8 }; // +8 to make it center of chunk + // +8 to make it center of chunk + int xCoord = chunkX * 16 + 8; + int zCoord = chunkZ * 16 + 8; + DebugLogger.finer("Decoded to coordinates: %d, %d", xCoord, zCoord); + + return new int[] { xCoord, zCoord }; } private long wordIndexesToCombinedValue(int[] wordIndexes) { long combinedValue = 0; for (int i=0; i>= bitsPerWord; - return combinedValue; } 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 index caff8ac..75d03e2 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java @@ -8,7 +8,7 @@ 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; @@ -19,40 +19,90 @@ public class Encoder { } public String[] encode(int xCoord, int zCoord) { - xCoord = Math.floorDiv(xCoord, 16); - zCoord = Math.floorDiv(zCoord, 16); - DebugLogger.finer("Chunk: %d, %d", xCoord, 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); - int wordsRequired = findWordsRequired(xCoord, zCoord); - DebugLogger.finer("Words required: %d", wordsRequired); + // 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. - int bitsRequired = wordsRequired * bitsPerWord; - int bitsRequiredPerCoordinate = bitsRequired / 2; - DebugLogger.finer("Bits required: %d (per coord: %d)", bitsRequired, bitsRequiredPerCoordinate); + // 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(xCoord, bitsRequiredPerCoordinate); - int encodedZ = encodeCoord(zCoord, 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 n = Math.max(Math.abs(x), Math.abs(z)); - return n == 0 ? 1 : 32 - Integer.numberOfLeadingZeros(n); - } + int maxVal = Math.max(x, z); + int minVal = Math.min(x, z); - private int findWordsRequired(int x, int z) { - int brpc = findBitsRequiredPerCoordinate(x, z); - return Math.ceilDiv(brpc * 2, wordList.getBitsPerWord()); + // 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) { From 41583939acf713b16838038c3eeb536605268f98 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 6 Apr 2025 11:29:50 +0200 Subject: [PATCH 84/89] Use component --- .../module/wordcoords/WordCoordsModule.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java index de442aa..a052b42 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java @@ -9,6 +9,12 @@ 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; @@ -79,14 +85,34 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { if (encode) { words = converter.encode(x, z); + String encoded = "///" + String.join(".", words); - sender.sendMessage("%d, %d encodes to ///%s".formatted(x, z, 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 { int[] xz = converter.decode(words); x = xz[0]; z = xz[1]; - sender.sendMessage("///%s decodes to around %d, %d".formatted(String.join(".", words), x, z)); + 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 + .append("±8") + .color(ChatColor.GRAY) + .create(); + sender.spigot().sendMessage(components); } return true; From 4f752bef61bffaba1c542aa4f622acaa86675e97 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sun, 6 Apr 2025 12:05:28 +0200 Subject: [PATCH 85/89] Quick mode --- .../module/wordcoords/WordCoordsModule.java | 70 ++++++++++++------- src/main/resources/strings.properties | 4 +- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java index a052b42..603b33d 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java @@ -19,13 +19,17 @@ 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 { +public class WordCoordsModule extends TweaksModule implements CommandExecutor, Listener { private WordList wordList; private WordCoordsConverter converter; @@ -40,6 +44,7 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { this.converter = new WordCoordsConverter(wordList); registerCommand("wordcoords", this); + registerEvents(this); } @Override @@ -59,28 +64,21 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { 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]); + } 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; - } + 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; + x = (int) dx; + z = (int) dz; - encode = true; - } catch (NumberFormatException ignored) { } - } - - if (!encode) { - String strArgs = String.join(" ", args); - words = smartDetectWords(strArgs); - } + encode = true; + } catch (NumberFormatException ignored) { } } if (encode) { @@ -98,9 +96,22 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { sender.spigot().sendMessage(components); } else { - int[] xz = converter.decode(words); - x = xz[0]; - z = xz[1]; + 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); @@ -109,7 +120,9 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { .color(ChatColor.GRAY) .append("%d, %d".formatted(x, z)) .color(ChatColor.AQUA) // TODO improve color - .append("±8") + .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); @@ -141,4 +154,13 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor { return words.toArray(String[]::new); } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + if (event.getMessage().startsWith("///")) { + event.setCancelled(true); + + event.getPlayer().performCommand("wordcoords " + event.getMessage().substring(3)); + } + } } diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index e9dda4d..b628eab 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -42,4 +42,6 @@ durabilityDisabled = Disabled durability alert # When console executes /wordcoords without arguments wordCoordsPlayerOnly = Only players can execute this command without arguments. -wordCoordsOutOfRange = Those coordinates are invalid. \ No newline at end of file +wordCoordsOutOfRange = Those coordinates are invalid. +wordCoordsInvalidWord = Invalid word: "%s" +wordCoordsNoWords = Please provide the Z coordinate. \ No newline at end of file From a8e67dbe266a84e3625899ddc65a0acda8a99099 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 14 May 2025 19:06:04 +0200 Subject: [PATCH 86/89] Document TweaksModule Signed-off-by: Minecon724 --- .../eu/m724/tweaks/module/TweaksModule.java | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/module/TweaksModule.java b/src/main/java/eu/m724/tweaks/module/TweaksModule.java index f554a8e..6cf6191 100644 --- a/src/main/java/eu/m724/tweaks/module/TweaksModule.java +++ b/src/main/java/eu/m724/tweaks/module/TweaksModule.java @@ -21,32 +21,60 @@ import java.lang.reflect.InvocationTargetException; import java.util.function.Consumer; public abstract class TweaksModule { + /** + * Called on module initialize. + */ protected abstract void onInit(); void init() { var name = getClass().getSimpleName(); - DebugLogger.finer("Initializing " + name); + DebugLogger.finer("Initializing module " + name); + long start = System.nanoTime(); this.onInit(); long end = System.nanoTime(); + DebugLogger.fine("Initialized %s in %d µs", name, (end - start) / 1000); } + /** + * Gets the plugin instance. + * + * @return The plugin instance + */ protected TweaksPlugin getPlugin() { return TweaksPlugin.getInstance(); } + /** + * Gets the plugin config. + * + * @return The plugin config + */ protected TweaksConfig getConfig() { return TweaksConfig.getConfig(); } + /** + * Registers an event listener. + * + * @param listener The event listener + */ protected void registerEvents(Listener listener) { - DebugLogger.finer("Registered listener: " + listener.getClass().getName()); getPlugin().getServer().getPluginManager().registerEvents(listener, getPlugin()); + + DebugLogger.finer("Registered event listener: " + listener.getClass().getName()); } + /** + * Registers an OUTGOING packet listener. + * Priority is {@link ListenerPriority}.NORMAL. + * + * @param packetType The {@link PacketType} to listen for + * @param consumer The consumer that will be called when the packet is received. + */ protected void onPacketSend(PacketType packetType, Consumer consumer) { ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) { @Override @@ -55,9 +83,16 @@ public abstract class TweaksModule { } }); - DebugLogger.finer("Registered packet send: " + packetType.name()); + DebugLogger.finer("Registered outgoing packet listener: " + packetType.name()); } + /** + * Registers an INCOMING packet listener. + * Priority is {@link ListenerPriority}.NORMAL. + * + * @param packetType The {@link PacketType} to listen for + * @param consumer The consumer that will be called when the packet is received. + */ protected void onPacketReceive(PacketType packetType, Consumer consumer) { ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) { @Override @@ -66,14 +101,27 @@ public abstract class TweaksModule { } }); - DebugLogger.finer("Registered packet receive: " + packetType.name()); + DebugLogger.finer("Registered incoming packet listener: " + packetType.name()); } + /** + * Registers a command. + * + * @param command The command + * @param executor The command executor + */ protected void registerCommand(String command, CommandExecutor executor) { getPlugin().getCommand(command).setExecutor(executor); DebugLogger.finer("Registered command: " + command); } + /** + * Initializes a module. + * + * @param clazz The class of the initialized module + * @return The module instance + * @param The type of the initialized module + */ public static T init(Class clazz) { T module; try { From e3f34ec46fa82c50c25b139b257fdb7ee364e692 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Wed, 14 May 2025 19:06:11 +0200 Subject: [PATCH 87/89] Refactor pomodoro Signed-off-by: Minecon724 --- .../module/pomodoro/PlayerPomodoro.java | 81 ++++++++++--------- .../pomodoro/PlayerPomodoroTracker.java | 29 +++++++ .../module/pomodoro/PomodoroCommands.java | 30 ++++--- .../module/pomodoro/PomodoroListener.java | 60 ++++++++------ .../module/pomodoro/PomodoroModule.java | 76 +++++++++++++++++ .../module/pomodoro/PomodoroRunnable.java | 45 +++++++---- .../tweaks/module/pomodoro/Pomodoros.java | 71 ---------------- src/main/resources/strings.properties | 10 ++- 8 files changed, 244 insertions(+), 158 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java delete mode 100644 src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java index 7b7954c..331c1c6 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java @@ -6,70 +6,77 @@ package eu.m724.tweaks.module.pomodoro; +import java.util.concurrent.TimeUnit; + public class PlayerPomodoro { - private int pomodori = 0; + private int intervalsDone = 0; - private boolean isBreak = false; - // this is for both break and not break - private long intervalStart = -1; + private boolean breaktime = false; + private long currentIntervalStartedAtNanos = -1; - /** - * A "pomodoro" is the 25-minute cycle you take breaks after
- * This returns how many cycles already elapsed, so if this is the first cycle this is 0
- * The break after the "pomodoro," so if it's breaktime after the first "pomodoro" it stays at 0 - */ - public int getPomodori() { - return pomodori; + public int getIntervalsDone() { + return intervalsDone; + } + + public boolean isBreaktime() { + return breaktime; + } + + public boolean isLongBreak() { + return (intervalsDone + 1) % PomodoroModule.INTERVALS_BEFORE_LONG_BREAK == 0; } /** - * When did the current interval start
- * Or when did the break start - * - * @see PlayerPomodoro#isBreak() + * @return The time the current interval or break started, in milliseconds */ - public long getIntervalStart() { - return intervalStart; + public long getCurrentIntervalStartedAtNanos() { + return currentIntervalStartedAtNanos; } - public int getCycleDurationSeconds() { - return isBreak ? (pomodori < 3 ? 300 : 1200) : 1500; + public int getCurrentIntervalDurationSeconds() { + if (breaktime) { + if (isLongBreak()) { + return PomodoroModule.LONG_BREAK_DURATION_SECONDS; + } + + return PomodoroModule.SHORT_BREAK_DURATION_SECONDS; + } else { + return PomodoroModule.INTERVAL_DURATION_SECONDS; + } } - public long getRemainingSeconds(long now) { - return getCycleDurationSeconds() - (now - getIntervalStart()) / 1000000000; + public long getCurrentIntervalDurationNanos() { + return TimeUnit.SECONDS.toNanos(getCurrentIntervalDurationSeconds()); } - /** - * Is it a break currently - */ - public boolean isBreak() { - return isBreak; + public long getCurrentIntervalRemainingNanos(long nowNanos) { + long elapsed = nowNanos - getCurrentIntervalStartedAtNanos(); + return getCurrentIntervalDurationNanos() - elapsed; } - public boolean isCycleComplete() { - return intervalStart + getCycleDurationSeconds() * 1000000000L < System.nanoTime(); + public boolean isIntervalComplete(long nowNanos) { + return currentIntervalStartedAtNanos + getCurrentIntervalDurationNanos() < nowNanos; } /** * Resets and starts the timer */ public void start() { - this.pomodori = 0; - this.isBreak = false; - this.intervalStart = System.nanoTime(); + this.intervalsDone = 0; + this.breaktime = false; + this.currentIntervalStartedAtNanos = System.nanoTime(); } /** * Completes a cycle */ - public void next() { - if (isBreak) { // from break to interval - this.pomodori++; - this.pomodori %= 4; + public void startBreakOrNextInterval() { + if (breaktime) { // from break to interval + this.intervalsDone++; + this.intervalsDone %= PomodoroModule.INTERVALS_BEFORE_LONG_BREAK; } - this.intervalStart = System.nanoTime(); - isBreak = !isBreak; + this.currentIntervalStartedAtNanos = System.nanoTime(); + breaktime = !breaktime; } } diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java new file mode 100644 index 0000000..92e3c6f --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java @@ -0,0 +1,29 @@ +/* + * 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.pomodoro; + +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerPomodoroTracker { + static final Map timers = new HashMap<>(); + + public static PlayerPomodoro get(Player player) { + return timers.get(player.getUniqueId()); + } + + public static PlayerPomodoro create(Player player) { + return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro()); + } + + public static boolean remove(Player player) { + return timers.remove(player.getUniqueId()) != null; + } +} diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java index 55f9685..ee452ab 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java @@ -6,6 +6,9 @@ package eu.m724.tweaks.module.pomodoro; +import eu.m724.tweaks.Language; +import eu.m724.tweaks.config.TweaksConfig; +import net.md_5.bungee.api.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -18,25 +21,34 @@ public class PomodoroCommands implements CommandExecutor { Player player = (Player) sender; String action = args.length > 0 ? args[0] : null; - PlayerPomodoro pomodoro = Pomodoros.get(player); + PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player); + + long now = System.nanoTime(); if (pomodoro != null) { if ("stop".equals(action)) { - Pomodoros.remove(player); - sender.sendMessage("Pomodoro disabled"); + PlayerPomodoroTracker.remove(player); + sender.spigot().sendMessage(Language.getComponent("pomodoroStopped", ChatColor.GREEN, label)); } else { - if (pomodoro.isCycleComplete()) { - pomodoro.next(); + if (pomodoro.isIntervalComplete(now)) { + pomodoro.startBreakOrNextInterval(); + + if (pomodoro.isBreaktime() && TweaksConfig.getConfig().pomodoroForce()) { + player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText()); + } } - sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(System.nanoTime()))); + + sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now)); } } else { if ("start".equals(action)) { - pomodoro = Pomodoros.create(player); + pomodoro = PlayerPomodoroTracker.create(player); pomodoro.start(); - sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getCycleDurationSeconds())); + + sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now)); } else { - sender.sendMessage("Start pomodoro with /pom start"); + // TODO help? + sender.spigot().sendMessage(Language.getComponent("pomodoroStart", ChatColor.GOLD, label)); } } diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java index 077e36e..853215e 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java @@ -7,56 +7,68 @@ package eu.m724.tweaks.module.pomodoro; import eu.m724.tweaks.config.TweaksConfig; -import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.*; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; public class PomodoroListener implements Listener { - private final boolean force = TweaksConfig.getConfig().pomodoroForce(); + private final TweaksConfig config = TweaksConfig.getConfig(); @EventHandler public void onPlayerLogin(PlayerLoginEvent event) { + // Joining ends break Player player = event.getPlayer(); - PlayerPomodoro pomodoro = Pomodoros.get(player); + PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player); if (pomodoro == null) return; - long remaining = pomodoro.getRemainingSeconds(System.nanoTime()); + long now = System.nanoTime(); + long remaining = pomodoro.getCurrentIntervalRemainingNanos(now); - if (pomodoro.isBreak()) { - if (pomodoro.isCycleComplete()) { - pomodoro.next(); + if (pomodoro.isBreaktime()) { + if (remaining > 0 && config.pomodoroForce()) { + player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText()); } else { - if (force) { - event.getPlayer().kickPlayer( - new ComponentBuilder() - .append(Pomodoros.formatTimer(pomodoro, remaining)) - .build().toLegacyText() - ); - } + pomodoro.startBreakOrNextInterval(); } } } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { + // Quitting starts break Player player = event.getPlayer(); - PlayerPomodoro pomodoro = Pomodoros.get(player); + PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player); if (pomodoro == null) return; - if (!pomodoro.isBreak() && pomodoro.isCycleComplete()) { - pomodoro.next(); + if (pomodoro.isBreaktime()) return; + + long now = System.nanoTime(); + long remaining = pomodoro.getCurrentIntervalRemainingNanos(now); + + if (remaining <= 0) { + pomodoro.startBreakOrNextInterval(); } } @EventHandler - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - PlayerPomodoro timer = Pomodoros.get(player); - if (timer == null) return; + public void onPlayerToggleSneak(PlayerToggleSneakEvent event) { + // Sneaking ends break + if (!event.isSneaking()) return; - if (timer.isBreak() && timer.getRemainingSeconds(System.nanoTime()) <= 0) - timer.next(); // resume timer if break ended + Player player = event.getPlayer(); + PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player); + if (pomodoro == null) return; + + if (!pomodoro.isBreaktime()) return; + + long now = System.nanoTime(); + long remaining = pomodoro.getCurrentIntervalRemainingNanos(now); + + if (remaining <= 0) { + pomodoro.startBreakOrNextInterval(); + } } } diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java index 89dd3d5..c97da7d 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java @@ -6,9 +6,23 @@ package eu.m724.tweaks.module.pomodoro; +import eu.m724.tweaks.Language; +import eu.m724.tweaks.config.TweaksConfig; 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.ComponentBuilder; + +import java.util.concurrent.TimeUnit; public class PomodoroModule extends TweaksModule { + static final int INTERVAL_DURATION_SECONDS = 10; + static final int SHORT_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(5); + static final int LONG_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(20); + static final int INTERVALS_BEFORE_LONG_BREAK = 4; + + static final int KICK_DELAY_SECONDS = 60; + @Override protected void onInit() { registerEvents(new PomodoroListener()); @@ -16,4 +30,66 @@ public class PomodoroModule extends TweaksModule { registerCommand("pomodoro", new PomodoroCommands()); } + + /** + * Gets a formatted timer for a player. + * + * @param pomodoro the player's {@link PlayerPomodoro} instance + * @param nowNanos unix now timestamp in nanoseconds + * @return the timer as {@link BaseComponent} + */ + static BaseComponent formatTimer(PlayerPomodoro pomodoro, long nowNanos) { + ComponentBuilder builder = new ComponentBuilder(); + + long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(nowNanos); + long remainingSeconds = TimeUnit.NANOSECONDS.toSeconds(remainingNanos); + + if (pomodoro.isBreaktime()) { + if (pomodoro.isLongBreak()) { + builder.append(Language.getComponent("pomodoroLongBreak", ChatColor.LIGHT_PURPLE)); + } else { + builder.append(Language.getComponent("pomodoroShortBreak", ChatColor.LIGHT_PURPLE)); + } + + if (remainingNanos > 0) { + builder.append(" %02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60)) + .color(ChatColor.GOLD); + } else { + builder.append(" 00:00") + .color(ChatColor.GREEN); + + if (!TweaksConfig.getConfig().pomodoroForce()) { + builder.append( "/pom").color(ChatColor.GOLD); + } + } + } else { + if (remainingNanos > 0) { + builder + .append("%02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60)) + .color(ChatColor.GRAY); + } else { + builder + .append("00:00") + .color(remainingSeconds % 2 == 0 ? ChatColor.RED : ChatColor.GRAY); + + if (!TweaksConfig.getConfig().pomodoroForce()) { + builder.append( "/pom").color(ChatColor.GOLD); + } + } + } + + + for (int i=0; i pomodoro.getIntervalsDone()) { + color = ChatColor.DARK_GRAY; + } + + builder.append(" o").color(color); + } + + return builder.build(); + } } diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java index 1b70d5f..f9bd924 100644 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java +++ b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java @@ -9,34 +9,49 @@ package eu.m724.tweaks.module.pomodoro; import eu.m724.tweaks.TweaksPlugin; import eu.m724.tweaks.config.TweaksConfig; import net.md_5.bungee.api.ChatMessageType; -import org.bukkit.Bukkit; import org.bukkit.Sound; +import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import java.util.concurrent.TimeUnit; + public class PomodoroRunnable extends BukkitRunnable { - private final boolean force = TweaksConfig.getConfig().pomodoroForce(); + private final TweaksConfig config = TweaksConfig.getConfig(); private final Plugin plugin = TweaksPlugin.getInstance(); // used only to kick @Override public void run() { long now = System.nanoTime(); - Bukkit.getOnlinePlayers().forEach(player -> { - PlayerPomodoro pomodoro = Pomodoros.get(player); - if (pomodoro == null) return; + PlayerPomodoroTracker.timers.forEach((uuid, pomodoro) -> { + long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(now); + long remainingSecs = TimeUnit.NANOSECONDS.toSeconds(remainingNanos); - long remaining = pomodoro.getRemainingSeconds(now); - // TODO make not always on - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, Pomodoros.formatTimer(pomodoro, remaining)); + // TODO optimize? + Player player = plugin.getServer().getPlayer(uuid); - if (remaining <= 0) { - player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f); - if (remaining < -60 && force) { - plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { - pomodoro.next(); - player.kickPlayer(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now)).toLegacyText()); - }); + if (player != null && player.isOnline()) { + // TODO make not always on + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, PomodoroModule.formatTimer(pomodoro, now)); + + if (remainingNanos <= 0) { + player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f); + + if (remainingSecs < -PomodoroModule.KICK_DELAY_SECONDS && config.pomodoroForce()) { + pomodoro.startBreakOrNextInterval(); + + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> + player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText()) + ); + } + } + } else { + if (remainingNanos <= 0) { + // Start break automatically if the player is offline + if (!pomodoro.isBreaktime()) { + pomodoro.startBreakOrNextInterval(); + } } } }); diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java b/src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java deleted file mode 100644 index 43cb412..0000000 --- a/src/main/java/eu/m724/tweaks/module/pomodoro/Pomodoros.java +++ /dev/null @@ -1,71 +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.pomodoro; - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class Pomodoros { - static final Map timers = new HashMap<>(); - - public static PlayerPomodoro get(Player player) { - return timers.get(player.getUniqueId()); - } - - public static PlayerPomodoro create(Player player) { - return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro()); - } - - public static boolean remove(Player player) { - return timers.remove(player.getUniqueId()) != null; - } - - static BaseComponent formatTimer(PlayerPomodoro pomodoro, long remaining) { - ComponentBuilder builder = new ComponentBuilder(); - - if (pomodoro.isBreak()) { - builder.append("Break ").color(ChatColor.LIGHT_PURPLE); - if (remaining > 0) { - builder.append("%02d:%02d".formatted(remaining / 60, remaining % 60)) - .color(ChatColor.GOLD); - } else { - builder.append("00:00") - .color(ChatColor.GREEN); - } - } else { - if (remaining > 0) { - builder - .append("%02d:%02d".formatted(remaining / 60, remaining % 60)) - .color(ChatColor.GRAY); - } else { - builder - .append("00:00") - .color(remaining % 2 == 0 ? ChatColor.RED : ChatColor.YELLOW); - } - } - - - for (int i=0; i<4; i++) { - ChatColor color = ChatColor.GRAY; - if (i == pomodoro.getPomodori()) { - color = ChatColor.LIGHT_PURPLE; - } else if (i > pomodoro.getPomodori()) { - color = ChatColor.DARK_GRAY; - } - - builder.append(" o").color(color); - } - - return builder.build(); - } -} diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index b628eab..204bc20 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -30,7 +30,7 @@ chatAlreadyHere = You're already in this room. authKickWrongKey = You're connecting to the wrong server address. You must connect to the one you're registered to. # If force is enabled and player is not registered. Changing this reveals you're using this plugin authKickUnregistered = You are not whitelisted on this server! -authKickError = An error occured. Please try again. If this persists, contact an administrator. +authKickError = An error occurred. Please try again. If this persists, contact an administrator. redstoneGatewayItem = Redstone gateway @@ -44,4 +44,10 @@ durabilityDisabled = Disabled durability alert 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 +wordCoordsNoWords = Please provide the Z coordinate. + +# /pomodoro +pomodoroStopped = Pomodoro stopped. Restart it with /%s start +pomodoroStart = Start pomodoro with /%s start +pomodoroShortBreak = Short break +pomodoroLongBreak = Long break \ No newline at end of file From 352807483c75c1c66c6b8e769d0b277662bcb69e Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Thu, 15 May 2025 09:03:48 +0200 Subject: [PATCH 88/89] Refactor DebugLogger Signed-off-by: Minecon724 --- src/main/java/eu/m724/tweaks/DebugLogger.java | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java index 9bf66c6..803b52d 100644 --- a/src/main/java/eu/m724/tweaks/DebugLogger.java +++ b/src/main/java/eu/m724/tweaks/DebugLogger.java @@ -10,8 +10,11 @@ import eu.m724.tweaks.module.TweaksModule; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class DebugLogger { + private DebugLogger() {} static Logger logger; public static void info(String message, Object... format) { @@ -35,20 +38,16 @@ public class DebugLogger { } private static void log(Level level, String message, Object... format) { - if (logger.getLevel().intValue() > level.intValue()) return; - var caller = Thread.currentThread().getStackTrace()[3].getClassName(); - - if (caller.equals(TweaksModule.class.getName())) { - var pcaller = Thread.currentThread().getStackTrace()[4].getClassName(); - if (pcaller.endsWith("Module")) - caller = pcaller; + if (!logger.isLoggable(level)) { + return; } - if (caller.startsWith("eu.m724.tweaks.")) - caller = caller.substring(15); + message = message.formatted(format); - message = "[" + caller + "] " + message.formatted(format); + if (logger.getLevel().intValue() <= Level.FINE.intValue()) { + message = "[" + getCaller() + "] " + message; + } if (level.intValue() < Level.INFO.intValue()) { // levels below info are never logged even if set for some reason // colors text gray (cyan is close to gray) @@ -61,5 +60,30 @@ public class DebugLogger { } logger.log(level, message); + + } + + private static String getCaller() { + String caller = Thread.currentThread().getStackTrace()[4].getClassName(); + + // TweaksModule has helper functions that log, we want to label the logs + if (caller.equals(TweaksModule.class.getName())) { + String pcaller = Thread.currentThread().getStackTrace()[5].getClassName(); + if (pcaller.endsWith("Module")) + caller = pcaller; + } + + if (caller.startsWith("eu.m724.tweaks.")) { + caller = caller.substring(15); + + String[] packages = caller.split("\\."); + + caller = IntStream.range(0, packages.length - 1) + .mapToObj(i -> packages[i].substring(0, 2)) + .collect(Collectors.joining(".")) + "." + packages[packages.length - 1]; + // TODO leading dot or no dot? + } + + return caller; } } From 2c835a4eab4c63a72290d15d9dc135e31793f756 Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Fri, 16 May 2025 10:22:01 +0200 Subject: [PATCH 89/89] Improve WordCoords Signed-off-by: Minecon724 --- .../module/wordcoords/WordCoordsCodec.java | 45 + .../wordcoords/WordCoordsConverter.java | 36 - .../module/wordcoords/WordCoordsModule.java | 179 +- .../tweaks/module/wordcoords/WordList.java | 2 +- .../DecoderWordsToCoords.java} | 20 +- .../EncoderCoordsToWords.java} | 43 +- src/main/resources/strings.properties | 6 +- src/main/resources/wordlist.txt | 2054 +++++++++++++++++ 8 files changed, 2222 insertions(+), 163 deletions(-) create mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsCodec.java delete mode 100644 src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java rename src/main/java/eu/m724/tweaks/module/wordcoords/{converter/Decoder.java => codec/DecoderWordsToCoords.java} (79%) rename src/main/java/eu/m724/tweaks/module/wordcoords/{converter/Encoder.java => codec/EncoderCoordsToWords.java} (65%) create mode 100644 src/main/resources/wordlist.txt diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsCodec.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsCodec.java new file mode 100644 index 0000000..302ecab --- /dev/null +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsCodec.java @@ -0,0 +1,45 @@ +/* + * 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.codec.DecoderWordsToCoords; +import eu.m724.tweaks.module.wordcoords.codec.EncoderCoordsToWords; + +import java.util.NoSuchElementException; + +public class WordCoordsCodec { + private final EncoderCoordsToWords encoder; + private final DecoderWordsToCoords decoder; + + public WordCoordsCodec(WordList wordList) { + this.encoder = new EncoderCoordsToWords(wordList); + this.decoder = new DecoderWordsToCoords(wordList); + + DebugLogger.fine("Words: %d (%d bits/w)", wordList.getWordCount(), wordList.getBitsPerWord()); + } + + /** + * Encodes coords to words + * @param x The X coordinate + * @param z The Z coordinate + * @return The words + */ + public String[] encodeWords(int x, int z) { + return encoder.encodeWords(x, z); + } + + /** + * Decodes words to coords + * @param words The words + * @return The X,Z coordinates + * @throws NoSuchElementException if one or more words are invalid + */ + public int[] decodeCoords(String[] words) throws NoSuchElementException { + return decoder.decodeCoords(words); + } +} 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 index 603b33d..01f9101 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java @@ -6,6 +6,7 @@ package eu.m724.tweaks.module.wordcoords; +import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.Language; import eu.m724.tweaks.module.TweaksModule; import net.md_5.bungee.api.ChatColor; @@ -25,35 +26,64 @@ 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.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.NoSuchElementException; public class WordCoordsModule extends TweaksModule implements CommandExecutor, Listener { - private WordList wordList; - private WordCoordsConverter converter; + private static final int MAX_RADIUS = 30_000_000; + + private WordCoordsCodec converter; @Override protected void onInit() { - try { - this.wordList = WordList.fromFile(getPlugin().getDataFolder().toPath().resolve("storage/wordlist.txt")); - } catch (IOException e) { - throw new RuntimeException(e); + Path wordListFile = getPlugin().getDataFolder().toPath().resolve("storage/wordlist.txt"); + + if (Files.notExists(wordListFile)) { + try { + saveDefaultWordList(wordListFile); + } catch (IOException e) { + throw new RuntimeException("Failed to save default word list", e); + } } - this.converter = new WordCoordsConverter(wordList); + WordList wordList; + try { + wordList = WordList.fromFile(wordListFile); + } catch (IOException e) { + throw new RuntimeException("Failed to load word list", e); + } + + this.converter = new WordCoordsCodec(wordList); registerCommand("wordcoords", this); registerEvents(this); } + private void saveDefaultWordList(Path wordListFile) throws IOException { + try (InputStream is = getPlugin().getResource("wordlist.txt")) { + assert is != null; + Files.copy(is, wordListFile); + } + } + @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 + args = String.join(" ", args) + .replaceAll("[^\\p{L}\\p{N}\\s]", " ") + .trim() + .split(" +"); + + if (args.length == 1 && args[0].isEmpty()) + args = new String[0]; // empty split fix + + DebugLogger.fine("Args: %s %d", String.join(", ", args), args.length); + if (args.length == 0) { if (!(sender instanceof Player player)) { sender.sendMessage(Language.getString("wordCoordsPlayerOnly")); @@ -64,95 +94,80 @@ public class WordCoordsModule extends TweaksModule implements CommandExecutor, L 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]); + } else { + if (Character.isDigit(args[0].codePointAt(0))) { + 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)); + if (dx > MAX_RADIUS || dx < -MAX_RADIUS || dz > MAX_RADIUS || dz < -MAX_RADIUS) { + sender.spigot().sendMessage(Language.getComponent("wordCoordsOutOfRange", ChatColor.RED)); + return true; + } + + x = (int) dx; + z = (int) dz; + + encode = true; + } catch (NumberFormatException ignored) { } + } else { + sender.spigot().sendMessage(Language.getComponent("wordCoordsProvideZ", 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); + encodeAndSend(x, z, sender); } 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); + decodeAndSend(args, sender); } return true; } - private String[] smartDetectWords(String str) { - List words = new ArrayList<>(); - StringBuilder currentWord = new StringBuilder(); + private void encodeAndSend(int x, int z, CommandSender sender) { + String[] words = converter.encodeWords(x, z); + String encoded = "///" + String.join(".", words); - for (int i=0; i ".formatted(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(Language.getString("clickToCopy")))) + .create(); - if (Character.isLetter(c)) { - currentWord.append(c); - } else { - if (!currentWord.isEmpty()) { - words.add(currentWord.toString()); - currentWord.setLength(0); - } - } + sender.spigot().sendMessage(components); + } + + private void decodeAndSend(String[] words, CommandSender sender) { + int x, z; + + try { + int[] xz = converter.decodeCoords(words); + x = xz[0]; + z = xz[1]; + } catch (NoSuchElementException e) { + sender.spigot().sendMessage(Language.getComponent("wordCoordsInvalidWord", ChatColor.RED, e.getMessage())); + return; } - if (!currentWord.isEmpty()) { - words.add(currentWord.toString()); - } + String encoded = "///" + String.join(".", words); - return words.toArray(String[]::new); + BaseComponent[] components = new ComponentBuilder() + .append(encoded + " -> ") + .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(Language.getString("clickToCopy")))) + .append(" ±8") + .color(ChatColor.GRAY) + .create(); + sender.spigot().sendMessage(components); } @EventHandler diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordList.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordList.java index e05d9ba..6ccc0ec 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordList.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/WordList.java @@ -51,7 +51,7 @@ public class WordList { public static WordList fromFile(Path path) throws IOException { try (var lines = Files.lines(path)) { - var list = lines.filter(s -> !s.isBlank()) + var list = lines.filter(s -> !s.isBlank() && !s.startsWith("#")) .map(String::toLowerCase) .distinct() .toList(); diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java b/src/main/java/eu/m724/tweaks/module/wordcoords/codec/DecoderWordsToCoords.java similarity index 79% rename from src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java rename to src/main/java/eu/m724/tweaks/module/wordcoords/codec/DecoderWordsToCoords.java index 65ff762..66afef5 100644 --- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java +++ b/src/main/java/eu/m724/tweaks/module/wordcoords/codec/DecoderWordsToCoords.java @@ -4,7 +4,7 @@ * in the project root for the full license text. */ -package eu.m724.tweaks.module.wordcoords.converter; +package eu.m724.tweaks.module.wordcoords.codec; import eu.m724.tweaks.DebugLogger; import eu.m724.tweaks.module.wordcoords.WordList; @@ -12,16 +12,16 @@ import eu.m724.tweaks.module.wordcoords.WordList; import java.util.NoSuchElementException; import java.util.Arrays; -public class Decoder { +public class DecoderWordsToCoords { private final WordList wordList; private final int bitsPerWord; - public Decoder(WordList wordList) { + public DecoderWordsToCoords(WordList wordList) { this.wordList = wordList; this.bitsPerWord = wordList.getBitsPerWord(); } - public int[] decode(String[] words) throws NoSuchElementException { + public int[] decodeCoords(String[] words) throws NoSuchElementException { int[] wordIndexes = new int[words.length]; for (int i=0; i= 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. + 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; @@ -101,7 +83,6 @@ public class Encoder { p = 32 - Integer.numberOfLeadingZeros(requiredPositiveMagnitude - 1); } - // bits = p + 1 return p + 1; } @@ -119,7 +100,7 @@ public class Encoder { // Break into word indexes int[] wordIndexes = new int[wordsRequired]; - int currentIndex = wordsRequired; // Start filling from end of array + int currentIndex = wordsRequired; // Start filling from the end of the array for (int remainingBits = bitsRequired; remainingBits > 0; remainingBits -= bitsPerWord) { int wordMask = (1 << bitsPerWord) - 1; diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 204bc20..88a5ffd 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -34,7 +34,7 @@ authKickError = An error occurred. Please try again. If this persists, contact a redstoneGatewayItem = Redstone gateway -clickToCopy = Click to copy to clipboard +clickToCopy = Click to copy clickToExecuteCommand = Click to execute command durabilityEnabled = Enabled durability alert @@ -43,8 +43,8 @@ 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. +wordCoordsInvalidWord = Invalid word or coordinate: "%s" +wordCoordsProvideZ = Please provide the Z coordinate. # /pomodoro pomodoroStopped = Pomodoro stopped. Restart it with /%s start diff --git a/src/main/resources/wordlist.txt b/src/main/resources/wordlist.txt new file mode 100644 index 0000000..40300c5 --- /dev/null +++ b/src/main/resources/wordlist.txt @@ -0,0 +1,2054 @@ +# This file is the word list for WordCoords. +# You can replace this file with your own words. + +# Below is the BIP-39 English list +# https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md + +abandon +ability +able +about +above +absent +absorb +abstract +absurd +abuse +access +accident +account +accuse +achieve +acid +acoustic +acquire +across +act +action +actor +actress +actual +adapt +add +addict +address +adjust +admit +adult +advance +advice +aerobic +affair +afford +afraid +again +age +agent +agree +ahead +aim +air +airport +aisle +alarm +album +alcohol +alert +alien +all +alley +allow +almost +alone +alpha +already +also +alter +always +amateur +amazing +among +amount +amused +analyst +anchor +ancient +anger +angle +angry +animal +ankle +announce +annual +another +answer +antenna +antique +anxiety +any +apart +apology +appear +apple +approve +april +arch +arctic +area +arena +argue +arm +armed +armor +army +around +arrange +arrest +arrive +arrow +art +artefact +artist +artwork +ask +aspect +assault +asset +assist +assume +asthma +athlete +atom +attack +attend +attitude +attract +auction +audit +august +aunt +author +auto +autumn +average +avocado +avoid +awake +aware +away +awesome +awful +awkward +axis +baby +bachelor +bacon +badge +bag +balance +balcony +ball +bamboo +banana +banner +bar +barely +bargain +barrel +base +basic +basket +battle +beach +bean +beauty +because +become +beef +before +begin +behave +behind +believe +below +belt +bench +benefit +best +betray +better +between +beyond +bicycle +bid +bike +bind +biology +bird +birth +bitter +black +blade +blame +blanket +blast +bleak +bless +blind +blood +blossom +blouse +blue +blur +blush +board +boat +body +boil +bomb +bone +bonus +book +boost +border +boring +borrow +boss +bottom +bounce +box +boy +bracket +brain +brand +brass +brave +bread +breeze +brick +bridge +brief +bright +bring +brisk +broccoli +broken +bronze +broom +brother +brown +brush +bubble +buddy +budget +buffalo +build +bulb +bulk +bullet +bundle +bunker +burden +burger +burst +bus +business +busy +butter +buyer +buzz +cabbage +cabin +cable +cactus +cage +cake +call +calm +camera +camp +can +canal +cancel +candy +cannon +canoe +canvas +canyon +capable +capital +captain +car +carbon +card +cargo +carpet +carry +cart +case +cash +casino +castle +casual +cat +catalog +catch +category +cattle +caught +cause +caution +cave +ceiling +celery +cement +census +century +cereal +certain +chair +chalk +champion +change +chaos +chapter +charge +chase +chat +cheap +check +cheese +chef +cherry +chest +chicken +chief +child +chimney +choice +choose +chronic +chuckle +chunk +churn +cigar +cinnamon +circle +citizen +city +civil +claim +clap +clarify +claw +clay +clean +clerk +clever +click +client +cliff +climb +clinic +clip +clock +clog +close +cloth +cloud +clown +club +clump +cluster +clutch +coach +coast +coconut +code +coffee +coil +coin +collect +color +column +combine +come +comfort +comic +common +company +concert +conduct +confirm +congress +connect +consider +control +convince +cook +cool +copper +copy +coral +core +corn +correct +cost +cotton +couch +country +couple +course +cousin +cover +coyote +crack +cradle +craft +cram +crane +crash +crater +crawl +crazy +cream +credit +creek +crew +cricket +crime +crisp +critic +crop +cross +crouch +crowd +crucial +cruel +cruise +crumble +crunch +crush +cry +crystal +cube +culture +cup +cupboard +curious +current +curtain +curve +cushion +custom +cute +cycle +dad +damage +damp +dance +danger +daring +dash +daughter +dawn +day +deal +debate +debris +decade +december +decide +decline +decorate +decrease +deer +defense +define +defy +degree +delay +deliver +demand +demise +denial +dentist +deny +depart +depend +deposit +depth +deputy +derive +describe +desert +design +desk +despair +destroy +detail +detect +develop +device +devote +diagram +dial +diamond +diary +dice +diesel +diet +differ +digital +dignity +dilemma +dinner +dinosaur +direct +dirt +disagree +discover +disease +dish +dismiss +disorder +display +distance +divert +divide +divorce +dizzy +doctor +document +dog +doll +dolphin +domain +donate +donkey +donor +door +dose +double +dove +draft +dragon +drama +drastic +draw +dream +dress +drift +drill +drink +drip +drive +drop +drum +dry +duck +dumb +dune +during +dust +dutch +duty +dwarf +dynamic +eager +eagle +early +earn +earth +easily +east +easy +echo +ecology +economy +edge +edit +educate +effort +egg +eight +either +elbow +elder +electric +elegant +element +elephant +elevator +elite +else +embark +embody +embrace +emerge +emotion +employ +empower +empty +enable +enact +end +endless +endorse +enemy +energy +enforce +engage +engine +enhance +enjoy +enlist +enough +enrich +enroll +ensure +enter +entire +entry +envelope +episode +equal +equip +era +erase +erode +erosion +error +erupt +escape +essay +essence +estate +eternal +ethics +evidence +evil +evoke +evolve +exact +example +excess +exchange +excite +exclude +excuse +execute +exercise +exhaust +exhibit +exile +exist +exit +exotic +expand +expect +expire +explain +expose +express +extend +extra +eye +eyebrow +fabric +face +faculty +fade +faint +faith +fall +false +fame +family +famous +fan +fancy +fantasy +farm +fashion +fat +fatal +father +fatigue +fault +favorite +feature +february +federal +fee +feed +feel +female +fence +festival +fetch +fever +few +fiber +fiction +field +figure +file +film +filter +final +find +fine +finger +finish +fire +firm +first +fiscal +fish +fit +fitness +fix +flag +flame +flash +flat +flavor +flee +flight +flip +float +flock +floor +flower +fluid +flush +fly +foam +focus +fog +foil +fold +follow +food +foot +force +forest +forget +fork +fortune +forum +forward +fossil +foster +found +fox +fragile +frame +frequent +fresh +friend +fringe +frog +front +frost +frown +frozen +fruit +fuel +fun +funny +furnace +fury +future +gadget +gain +galaxy +gallery +game +gap +garage +garbage +garden +garlic +garment +gas +gasp +gate +gather +gauge +gaze +general +genius +genre +gentle +genuine +gesture +ghost +giant +gift +giggle +ginger +giraffe +girl +give +glad +glance +glare +glass +glide +glimpse +globe +gloom +glory +glove +glow +glue +goat +goddess +gold +good +goose +gorilla +gospel +gossip +govern +gown +grab +grace +grain +grant +grape +grass +gravity +great +green +grid +grief +grit +grocery +group +grow +grunt +guard +guess +guide +guilt +guitar +gun +gym +habit +hair +half +hammer +hamster +hand +happy +harbor +hard +harsh +harvest +hat +have +hawk +hazard +head +health +heart +heavy +hedgehog +height +hello +helmet +help +hen +hero +hidden +high +hill +hint +hip +hire +history +hobby +hockey +hold +hole +holiday +hollow +home +honey +hood +hope +horn +horror +horse +hospital +host +hotel +hour +hover +hub +huge +human +humble +humor +hundred +hungry +hunt +hurdle +hurry +hurt +husband +hybrid +ice +icon +idea +identify +idle +ignore +ill +illegal +illness +image +imitate +immense +immune +impact +impose +improve +impulse +inch +include +income +increase +index +indicate +indoor +industry +infant +inflict +inform +inhale +inherit +initial +inject +injury +inmate +inner +innocent +input +inquiry +insane +insect +inside +inspire +install +intact +interest +into +invest +invite +involve +iron +island +isolate +issue +item +ivory +jacket +jaguar +jar +jazz +jealous +jeans +jelly +jewel +job +join +joke +journey +joy +judge +juice +jump +jungle +junior +junk +just +kangaroo +keen +keep +ketchup +key +kick +kid +kidney +kind +kingdom +kiss +kit +kitchen +kite +kitten +kiwi +knee +knife +knock +know +lab +label +labor +ladder +lady +lake +lamp +language +laptop +large +later +latin +laugh +laundry +lava +law +lawn +lawsuit +layer +lazy +leader +leaf +learn +leave +lecture +left +leg +legal +legend +leisure +lemon +lend +length +lens +leopard +lesson +letter +level +liar +liberty +library +license +life +lift +light +like +limb +limit +link +lion +liquid +list +little +live +lizard +load +loan +lobster +local +lock +logic +lonely +long +loop +lottery +loud +lounge +love +loyal +lucky +luggage +lumber +lunar +lunch +luxury +lyrics +machine +mad +magic +magnet +maid +mail +main +major +make +mammal +man +manage +mandate +mango +mansion +manual +maple +marble +march +margin +marine +market +marriage +mask +mass +master +match +material +math +matrix +matter +maximum +maze +meadow +mean +measure +meat +mechanic +medal +media +melody +melt +member +memory +mention +menu +mercy +merge +merit +merry +mesh +message +metal +method +middle +midnight +milk +million +mimic +mind +minimum +minor +minute +miracle +mirror +misery +miss +mistake +mix +mixed +mixture +mobile +model +modify +mom +moment +monitor +monkey +monster +month +moon +moral +more +morning +mosquito +mother +motion +motor +mountain +mouse +move +movie +much +muffin +mule +multiply +muscle +museum +mushroom +music +must +mutual +myself +mystery +myth +naive +name +napkin +narrow +nasty +nation +nature +near +neck +need +negative +neglect +neither +nephew +nerve +nest +net +network +neutral +never +news +next +nice +night +noble +noise +nominee +noodle +normal +north +nose +notable +note +nothing +notice +novel +now +nuclear +number +nurse +nut +oak +obey +object +oblige +obscure +observe +obtain +obvious +occur +ocean +october +odor +off +offer +office +often +oil +okay +old +olive +olympic +omit +once +one +onion +online +only +open +opera +opinion +oppose +option +orange +orbit +orchard +order +ordinary +organ +orient +original +orphan +ostrich +other +outdoor +outer +output +outside +oval +oven +over +own +owner +oxygen +oyster +ozone +pact +paddle +page +pair +palace +palm +panda +panel +panic +panther +paper +parade +parent +park +parrot +party +pass +patch +path +patient +patrol +pattern +pause +pave +payment +peace +peanut +pear +peasant +pelican +pen +penalty +pencil +people +pepper +perfect +permit +person +pet +phone +photo +phrase +physical +piano +picnic +picture +piece +pig +pigeon +pill +pilot +pink +pioneer +pipe +pistol +pitch +pizza +place +planet +plastic +plate +play +please +pledge +pluck +plug +plunge +poem +poet +point +polar +pole +police +pond +pony +pool +popular +portion +position +possible +post +potato +pottery +poverty +powder +power +practice +praise +predict +prefer +prepare +present +pretty +prevent +price +pride +primary +print +priority +prison +private +prize +problem +process +produce +profit +program +project +promote +proof +property +prosper +protect +proud +provide +public +pudding +pull +pulp +pulse +pumpkin +punch +pupil +puppy +purchase +purity +purpose +purse +push +put +puzzle +pyramid +quality +quantum +quarter +question +quick +quit +quiz +quote +rabbit +raccoon +race +rack +radar +radio +rail +rain +raise +rally +ramp +ranch +random +range +rapid +rare +rate +rather +raven +raw +razor +ready +real +reason +rebel +rebuild +recall +receive +recipe +record +recycle +reduce +reflect +reform +refuse +region +regret +regular +reject +relax +release +relief +rely +remain +remember +remind +remove +render +renew +rent +reopen +repair +repeat +replace +report +require +rescue +resemble +resist +resource +response +result +retire +retreat +return +reunion +reveal +review +reward +rhythm +rib +ribbon +rice +rich +ride +ridge +rifle +right +rigid +ring +riot +ripple +risk +ritual +rival +river +road +roast +robot +robust +rocket +romance +roof +rookie +room +rose +rotate +rough +round +route +royal +rubber +rude +rug +rule +run +runway +rural +sad +saddle +sadness +safe +sail +salad +salmon +salon +salt +salute +same +sample +sand +satisfy +satoshi +sauce +sausage +save +say +scale +scan +scare +scatter +scene +scheme +school +science +scissors +scorpion +scout +scrap +screen +script +scrub +sea +search +season +seat +second +secret +section +security +seed +seek +segment +select +sell +seminar +senior +sense +sentence +series +service +session +settle +setup +seven +shadow +shaft +shallow +share +shed +shell +sheriff +shield +shift +shine +ship +shiver +shock +shoe +shoot +shop +short +shoulder +shove +shrimp +shrug +shuffle +shy +sibling +sick +side +siege +sight +sign +silent +silk +silly +silver +similar +simple +since +sing +siren +sister +situate +six +size +skate +sketch +ski +skill +skin +skirt +skull +slab +slam +sleep +slender +slice +slide +slight +slim +slogan +slot +slow +slush +small +smart +smile +smoke +smooth +snack +snake +snap +sniff +snow +soap +soccer +social +sock +soda +soft +solar +soldier +solid +solution +solve +someone +song +soon +sorry +sort +soul +sound +soup +source +south +space +spare +spatial +spawn +speak +special +speed +spell +spend +sphere +spice +spider +spike +spin +spirit +split +spoil +sponsor +spoon +sport +spot +spray +spread +spring +spy +square +squeeze +squirrel +stable +stadium +staff +stage +stairs +stamp +stand +start +state +stay +steak +steel +stem +step +stereo +stick +still +sting +stock +stomach +stone +stool +story +stove +strategy +street +strike +strong +struggle +student +stuff +stumble +style +subject +submit +subway +success +such +sudden +suffer +sugar +suggest +suit +summer +sun +sunny +sunset +super +supply +supreme +sure +surface +surge +surprise +surround +survey +suspect +sustain +swallow +swamp +swap +swarm +swear +sweet +swift +swim +swing +switch +sword +symbol +symptom +syrup +system +table +tackle +tag +tail +talent +talk +tank +tape +target +task +taste +tattoo +taxi +teach +team +tell +ten +tenant +tennis +tent +term +test +text +thank +that +theme +then +theory +there +they +thing +this +thought +three +thrive +throw +thumb +thunder +ticket +tide +tiger +tilt +timber +time +tiny +tip +tired +tissue +title +toast +tobacco +today +toddler +toe +together +toilet +token +tomato +tomorrow +tone +tongue +tonight +tool +tooth +top +topic +topple +torch +tornado +tortoise +toss +total +tourist +toward +tower +town +toy +track +trade +traffic +tragic +train +transfer +trap +trash +travel +tray +treat +tree +trend +trial +tribe +trick +trigger +trim +trip +trophy +trouble +truck +true +truly +trumpet +trust +truth +try +tube +tuition +tumble +tuna +tunnel +turkey +turn +turtle +twelve +twenty +twice +twin +twist +two +type +typical +ugly +umbrella +unable +unaware +uncle +uncover +under +undo +unfair +unfold +unhappy +uniform +unique +unit +universe +unknown +unlock +until +unusual +unveil +update +upgrade +uphold +upon +upper +upset +urban +urge +usage +use +used +useful +useless +usual +utility +vacant +vacuum +vague +valid +valley +valve +van +vanish +vapor +various +vast +vault +vehicle +velvet +vendor +venture +venue +verb +verify +version +very +vessel +veteran +viable +vibrant +vicious +victory +video +view +village +vintage +violin +virtual +virus +visa +visit +visual +vital +vivid +vocal +voice +void +volcano +volume +vote +voyage +wage +wagon +wait +walk +wall +walnut +want +warfare +warm +warrior +wash +wasp +waste +water +wave +way +wealth +weapon +wear +weasel +weather +web +wedding +weekend +weird +welcome +west +wet +whale +what +wheat +wheel +when +where +whip +whisper +wide +width +wife +wild +will +win +window +wine +wing +wink +winner +winter +wire +wisdom +wise +wish +witness +wolf +woman +wonder +wood +wool +word +work +world +worry +worth +wrap +wreck +wrestle +wrist +write +wrong +yard +year +yellow +you +young +youth +zebra +zero +zone +zoo