From ab9f4b052564178778b6305cc280288156169e81 Mon Sep 17 00:00:00 2001 From: Harrison Deng Date: Tue, 12 Nov 2024 06:51:42 +0000 Subject: [PATCH] Added sync command --- .gitignore | 4 +- .vscode/launch.json | 15 +++++ .vscode/tasks.json | 47 +++++++++++++- devserver/bukkit.yml | 32 ++++++++++ devserver/server.properties | 61 +++++++++++++++++++ devserver/start.sh | 4 +- .../spigotresourcesync/CommandController.java | 57 +++++++++++++++++ .../SpigotResourceSync.java | 8 ++- .../spigotresourcesync/SyncListManager.java | 15 +++++ .../commands/SyncCommand.java | 38 ++++++++++++ .../spigotresourcesync/data/SyncList.java | 14 +++-- src/main/resources/plugin.yml | 7 ++- .../spigotresourcesync/TestConfigManager.java | 3 +- .../spigotresourcesync/data/TestSyncList.java | 17 ++++++ 14 files changed, 311 insertions(+), 11 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 devserver/bukkit.yml create mode 100644 devserver/server.properties create mode 100644 src/main/java/solutions/reslate/entertainment/spigotresourcesync/CommandController.java create mode 100644 src/main/java/solutions/reslate/entertainment/spigotresourcesync/commands/SyncCommand.java create mode 100644 src/test/java/solutions/reslate/entertainment/spigotresourcesync/data/TestSyncList.java diff --git a/.gitignore b/.gitignore index bf9b9f4..dfb47a1 100644 --- a/.gitignore +++ b/.gitignore @@ -127,4 +127,6 @@ buildtools/* !buildtools/install.sh devserver/* !devserver/start.sh -!devserver/loadplugin.sh \ No newline at end of file +!devserver/server.properties +!devserver/loadplugin.sh +!devserver/bukkit.yml \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d795e35 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Development Server", + "request": "attach", + "hostName": "localhost", + "port": 5005, + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index eab3cbe..fbaefe2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,6 +2,7 @@ "version": "2.0.0", "tasks": [ { + "label": "Build Plugin to Development Server", "type": "java (buildArtifact)", "targetPath": "${workspaceFolder}/devserver/plugins/${workspaceFolderBasename}.jar", "elements": [ @@ -9,7 +10,49 @@ "${dependencies}" ], "problemMatcher": [], - "label": "Build SpigotResourceSync to plugins" + }, + { + "label": "Install Development Server", + "type": "shell", + "command": "${workspaceFolder}/buildtools/install.sh", + "options": { + "cwd": "${workspaceFolder}/buildtools" + }, + "problemMatcher": [] + }, + { + "label": "Start Development Server", + "type": "shell", + "isBackground": true, + "command": "${workspaceFolder}/devserver/start.sh", + "options": { + "cwd": "${workspaceFolder}/devserver" + }, + "dependsOn": [ + "Build Plugin to Development Server", + ], + "problemMatcher": [ + { + "source": "Spigot Server", + "fileLocation": [ + "autoDetect", + "${workspaceFolder}/src" + ], + "pattern": [ + { + "regexp": "^\\[\\d\\d:\\d\\d:\\d\\d\\] \\[[\\w\\s]+\/(\\w+)\\]: ([\\w \".()?]+\n[\\w \".()?:]+)$", + "severity": 1, + "message": 2 + }, + { + "regexp": "^\\s+at ([\\w.$]+)\\((\\w+\\.java):(\\d+)\\) ~\\[.+:.+\\]$", + "file": 2, + "line": 3, + "loop": true + } + ] + } + ] } - ] + ], } \ No newline at end of file diff --git a/devserver/bukkit.yml b/devserver/bukkit.yml new file mode 100644 index 0000000..d739ce3 --- /dev/null +++ b/devserver/bukkit.yml @@ -0,0 +1,32 @@ +settings: + allow-end: true + warn-on-overload: false + permissions-file: permissions.yml + update-folder: update + plugin-profiling: false + connection-throttle: 4000 + query-plugins: true + deprecated-verbose: default + shutdown-message: Server closed + minimum-api: none + use-map-color-cache: true +spawn-limits: + monsters: 70 + animals: 10 + water-animals: 5 + water-ambient: 20 + water-underground-creature: 5 + axolotls: 5 + ambient: 15 +chunk-gc: + period-in-ticks: 600 +ticks-per: + animal-spawns: 400 + monster-spawns: 1 + water-spawns: 1 + water-ambient-spawns: 1 + water-underground-creature-spawns: 1 + axolotl-spawns: 1 + ambient-spawns: 1 + autosave: 6000 +aliases: now-in-commands.yml diff --git a/devserver/server.properties b/devserver/server.properties new file mode 100644 index 0000000..3d9a94b --- /dev/null +++ b/devserver/server.properties @@ -0,0 +1,61 @@ +#Minecraft server properties +#Tue Nov 12 06:44:35 UTC 2024 +allow-flight=false +allow-nether=true +broadcast-console-to-ops=true +broadcast-rcon-to-ops=true +debug=false +difficulty=easy +enable-command-block=false +enable-jmx-monitoring=false +enable-query=false +enable-rcon=false +enable-status=true +enforce-secure-profile=true +enforce-whitelist=false +entity-broadcast-range-percentage=100 +force-gamemode=false +function-permission-level=2 +gamemode=survival +generate-structures=true +generator-settings={} +hardcore=false +hide-online-players=false +initial-disabled-packs= +initial-enabled-packs=vanilla +level-name=world +level-seed= +level-type=minecraft\:normal +log-ips=true +max-chained-neighbor-updates=1000000 +max-players=20 +max-tick-time=600000 +max-world-size=29999984 +motd=A Minecraft Server +network-compression-threshold=256 +online-mode=true +op-permission-level=4 +player-idle-timeout=0 +prevent-proxy-connections=false +pvp=true +query.port=25565 +rate-limit=0 +rcon.password= +rcon.port=25575 +require-resource-pack=false +resource-pack= +resource-pack-id= +resource-pack-prompt= +resource-pack-sha1= +server-ip= +server-port=25565 +simulation-distance=10 +spawn-animals=true +spawn-monsters=true +spawn-npcs=true +spawn-protection=16 +sync-chunk-writes=true +text-filtering-config= +use-native-transport=true +view-distance=10 +white-list=false diff --git a/devserver/start.sh b/devserver/start.sh index 4bddb68..1588196 100755 --- a/devserver/start.sh +++ b/devserver/start.sh @@ -1,3 +1,5 @@ #!/bin/sh -java -Xmx2G -XX:+UseG1GC -jar spigot.jar nogui \ No newline at end of file +echo "Server started" +java -Xmx2G -XX:+UseG1GC -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -jar spigot.jar nogui +echo "Server stopped" \ No newline at end of file diff --git a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/CommandController.java b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/CommandController.java new file mode 100644 index 0000000..fbd8ee9 --- /dev/null +++ b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/CommandController.java @@ -0,0 +1,57 @@ +package solutions.reslate.entertainment.spigotresourcesync; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + + +public class CommandController implements CommandExecutor { + private Set names; + private Map commands; + + + public CommandController() { + super(); + names = new HashSet<>(); + names.add("resourcesync"); + names.add("ressync"); + commands = new HashMap<>(); + } + + public void registerCommand(Command command) { + if (command == null) throw new IllegalArgumentException("Command cannot be null!"); + this.commands.put(command.getName(), command); + for (String alias : command.getAliases()) { + this.commands.put(alias, command); + } + } + + public void deregisterCommand(Command command) { + this.deregisterCommand(command.getName()); + } + + public void deregisterCommand(String commandName) { + if (commandName == null || commandName.isBlank()) throw new IllegalArgumentException("Command name cannot be null or blank."); + Command removed = this.commands.remove(commandName); + for (String alias : removed.getAliases()) { + this.commands.remove(alias); + } + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) return false; + if (commands.containsKey(args[0])) { + Command subcommand = commands.get(args[0]); + return subcommand.execute(sender, label, Arrays.copyOfRange(args, 1, args.length)); + } + return false; + } + +} diff --git a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SpigotResourceSync.java b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SpigotResourceSync.java index afdc727..ef65a16 100644 --- a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SpigotResourceSync.java +++ b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SpigotResourceSync.java @@ -5,12 +5,14 @@ import java.io.File; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.java.JavaPlugin; +import solutions.reslate.entertainment.spigotresourcesync.commands.SyncCommand; import solutions.reslate.entertainment.spigotresourcesync.serialisation.JacksonYamlSerialiser; import solutions.reslate.entertainment.spigotresourcesync.synchronisation.ApacheCommonsIOSynchroniser; public class SpigotResourceSync extends JavaPlugin { private ConfigManager configManager; private SyncListManager syncListManager; + private CommandController commandController; @Override public void onDisable() { @@ -26,11 +28,15 @@ public class SpigotResourceSync extends JavaPlugin { if (configManager.getConfiguration().getSyncOnLoad()) { syncListManager.synchroniseAllSyncList(); } + commandController = new CommandController(); + commandController.registerCommand(new SyncCommand(syncListManager)); super.onLoad(); } @Override public void onEnable() { + getLogger().info(getName()); + getCommand(getName()).setExecutor(commandController); super.onEnable(); } @@ -48,6 +54,6 @@ public class SpigotResourceSync extends JavaPlugin { public void saveDefaultConfig() { configManager.resetConfiguration(); configManager.flush(); - super.saveDefaultConfig(); } + } \ No newline at end of file diff --git a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SyncListManager.java b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SyncListManager.java index b60ec28..c14c797 100644 --- a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SyncListManager.java +++ b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/SyncListManager.java @@ -36,6 +36,21 @@ public class SyncListManager implements ObjectLoadListener { logger.info("Done synchronising."); } + public void synchroniseGroupSyncList(String group) { + logger.info("Synchronising group sync pairs..."); + for (SyncPair syncPair : this.configuration.getSyncList().gatherGroupSyncPairs(group)) { + File source = new File(syncPair.getSource()); + File dest = new File(syncPair.getDestination()); + try { + synchroniser.sync(source, dest); + logger.info(String.format("Synchronised \"%s\" to \"%s\"!", source.getName(), dest.getName())); + } catch (IOException e) { + logger.warning(String.format("Failed to synchronise \"%s\" to \"%s\". %s", source.getAbsolutePath(), dest.getAbsolutePath(), e.getMessage())); + } + } + logger.info("Done synchronising."); + } + @Override public void objectLoaded(Configuration obj) { logger.info("Updating synchronisation list due to recently loading configuration..."); diff --git a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/commands/SyncCommand.java b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/commands/SyncCommand.java new file mode 100644 index 0000000..8dca05a --- /dev/null +++ b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/commands/SyncCommand.java @@ -0,0 +1,38 @@ +package solutions.reslate.entertainment.spigotresourcesync.commands; + +import java.util.ArrayList; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import solutions.reslate.entertainment.spigotresourcesync.SyncListManager; + +public class SyncCommand extends Command { + private SyncListManager syncListManager; + + + public SyncCommand(SyncListManager syncListManager) { + super( + "sync", + "Synchronise based off your configurations.", + "sync [sync group name]", + new ArrayList<>() + ); + this.syncListManager = syncListManager; + } + + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + if (args.length > 1) return false; + if (args.length == 1) { + String groupName = args[0]; + syncListManager.synchroniseGroupSyncList(groupName); + sender.sendMessage(String.format("Synchronisation of \"%s\" complete!", groupName)); + } else { + syncListManager.synchroniseAllSyncList(); + sender.sendMessage("Synchronisation of all items complete!"); + } + return true; + } + +} diff --git a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/data/SyncList.java b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/data/SyncList.java index 7bbbaea..d773f28 100644 --- a/src/main/java/solutions/reslate/entertainment/spigotresourcesync/data/SyncList.java +++ b/src/main/java/solutions/reslate/entertainment/spigotresourcesync/data/SyncList.java @@ -2,6 +2,7 @@ package solutions.reslate.entertainment.spigotresourcesync.data; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -17,12 +18,17 @@ public class SyncList implements Serializable { this.syncPairs = new LinkedHashMap<>(); } - public List gatherAllSyncPairs() { + public SequencedCollection gatherAllSyncPairs() { List allSyncPairs = new ArrayList<>(); for (SequencedCollection syncPairs : this.syncPairs.values()) { allSyncPairs.addAll(syncPairs); } - return allSyncPairs; + return Collections.unmodifiableSequencedCollection(allSyncPairs); + } + + public SequencedCollection gatherGroupSyncPairs(String groupName) { + if (!this.syncPairs.containsKey(groupName)) throw new IllegalArgumentException(String.format("\"%s\" group does not exist!", groupName)); + return Collections.unmodifiableSequencedCollection(this.syncPairs.get(groupName)); } public void addSynchronisationPair(String source, String dest, String group) { @@ -52,8 +58,8 @@ public class SyncList implements Serializable { } } - public List gatherSynchronisationGroups() { - return new ArrayList<>(this.syncPairs.keySet()); + public SequencedCollection gatherSynchronisationGroups() { + return Collections.unmodifiableSequencedCollection(new ArrayList<>(this.syncPairs.keySet())); } public SequencedMap> getSyncPairs() { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 32826b0..2aad423 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,4 +1,9 @@ name: SpigotResourceSync version: 1.0.0 main: solutions.reslate.entertainment.spigotresourcesync.SpigotResourceSync -api-version: '1.20' \ No newline at end of file +api-version: '1.20' + +commands: + spigotresourcesync: + description: Tool suite for synchronisation resources across directories. + usage: See "/spigotresourcesync help" for help. \ No newline at end of file diff --git a/src/test/java/solutions/reslate/entertainment/spigotresourcesync/TestConfigManager.java b/src/test/java/solutions/reslate/entertainment/spigotresourcesync/TestConfigManager.java index 8ff6163..dfb6e55 100644 --- a/src/test/java/solutions/reslate/entertainment/spigotresourcesync/TestConfigManager.java +++ b/src/test/java/solutions/reslate/entertainment/spigotresourcesync/TestConfigManager.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.logging.Logger; import org.junit.jupiter.api.Test; @@ -27,6 +28,6 @@ public class TestConfigManager { assumeTrue(dummyConfig.exists()); ConfigManager finalConfigManager = new ConfigManager(dummyConfig, dummySerialiser, logger); finalConfigManager.load(); - assertEquals(dummySyncPair, finalConfigManager.getConfiguration().getSyncList().gatherAllSyncPairs().get(0)); + assertEquals(dummySyncPair, new ArrayList<>(finalConfigManager.getConfiguration().getSyncList().gatherAllSyncPairs()).get(1)); } } diff --git a/src/test/java/solutions/reslate/entertainment/spigotresourcesync/data/TestSyncList.java b/src/test/java/solutions/reslate/entertainment/spigotresourcesync/data/TestSyncList.java new file mode 100644 index 0000000..d7b8606 --- /dev/null +++ b/src/test/java/solutions/reslate/entertainment/spigotresourcesync/data/TestSyncList.java @@ -0,0 +1,17 @@ +package solutions.reslate.entertainment.spigotresourcesync.data; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.Test; + +public class TestSyncList { + @Test + void testGatherSyncGroup() { + SyncList dummyList = new SyncList(); + dummyList.addSynchronisationPair("abc", "def", "a"); + dummyList.addSynchronisationPair("ghi", "jkl", "a"); + dummyList.addSynchronisationPair("123", "456", "b"); + assertEquals(new SyncPair("abc", "def"), dummyList.gatherGroupSyncPairs("a").getFirst()); + } +}