From 29ae27adacac982b92c3a2dd52a31670d21bdc2e Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 17 Jul 2024 05:01:25 +0100 Subject: [PATCH 01/17] - First closed alpha build --- pom.xml | 4 +- .../ResourcePackManager.java | 7 +- .../autohost/AutoHost.java | 149 ++++++++++++++---- .../commands/CommandManager.java | 1 + .../DataComplianceRequestCommand.java | 43 +++++ .../config/BlueprintFolder.java | 46 ++++++ .../config/ConfigurationEngine.java | 9 ++ .../config/DefaultConfig.java | 12 ++ .../datacompliance/DataCompliance.java | 4 + .../resourcepackmanager/mixer/Mix.java | 21 ++- .../playermanager/PlayerManager.java | 16 ++ .../thirdparty/ItemsAdder.java | 11 +- .../resourcepackmanager/thirdparty/Nova.java | 11 +- .../thirdparty/Oraxen.java | 13 +- .../thirdparty/ResourcePackManager.java | 13 ++ .../thirdparty/ThirdPartyResourcePack.java | 9 +- .../utils/ChatColorConverter.java | 24 +++ .../utils/SHA1Generator.java | 25 +++ src/main/resources/ReadMe.md | 39 +++++ src/main/resources/pack.mcmeta | 6 + src/main/resources/pack.png | Bin 0 -> 22239 bytes src/main/resources/plugin.yml | 2 +- 22 files changed, 416 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/utils/ChatColorConverter.java create mode 100644 src/main/resources/ReadMe.md create mode 100644 src/main/resources/pack.mcmeta create mode 100644 src/main/resources/pack.png diff --git a/pom.xml b/pom.xml index bc2f010..239370e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.0-SNAPSHOT + 0.0.1 22 @@ -50,6 +50,8 @@ + ResourcePackManager + org.apache.maven.plugins diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 179a3af..6fcfe8b 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -2,8 +2,10 @@ import com.magmaguy.resourcepackmanager.autohost.AutoHost; import com.magmaguy.resourcepackmanager.commands.CommandManager; +import com.magmaguy.resourcepackmanager.config.BlueprintFolder; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.mixer.Mix; +import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; @@ -20,12 +22,15 @@ public void onEnable() { " | /\\__ \\ _/ |\\/| / _` | ' \\/ _` / _` / -_) '_|\n" + " |_|_\\|___/_| |_| |_\\__,_|_||_\\__,_\\__, \\___|_| \n" + " |___/ "); - Logger.info("Enabling ResourcePackManager v." + this.getDescription().getVersion()); + Logger.info("ResourcePackManager v." + this.getDescription().getVersion()); plugin = this; DefaultConfig.initializeConfig(); + BlueprintFolder.initialize(); Mix.initialize(); AutoHost.initialize(); new CommandManager(this); + if (DefaultConfig.isAutoHost()) + Bukkit.getPluginManager().registerEvents(new PlayerManager(), this); } @Override diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index a520e44..412ca91 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -4,99 +4,182 @@ import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.mixer.Mix; +import lombok.Getter; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.FileEntity; +import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.UUID; public class AutoHost { - private static final String hostURL = "http://localhost:3000/sha1"; - private static final String stillAliveURL = "http://localhost:3000/still_alive"; - private static final String rspURL = "http://localhost:3000/upload"; + // private static final String finalURL = "http://localhost:3000/"; + private static final String finalURL = "http://magmaguy.com:50000/"; + private static final UUID pluginRSPUUID = UUID.randomUUID(); private static BukkitTask keepAlive = null; + @Getter + private static String rspUUID = null; private AutoHost() { } + public static void sendResourcePack(Player player) { + if (rspUUID == null) return; + player.addResourcePack(pluginRSPUUID, finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); + } + public static void initialize() { if (!DefaultConfig.isAutoHost()) return; if (Mix.getFinalResourcePack() == null) return; + checkFileExistence(); keepAlive = new BukkitRunnable() { + int counter = 0; + @Override public void run() { - try { - if (!sendSHA1(Mix.getFinalSHA1(), hostURL)) { - uploadFile(Mix.getFinalResourcePack(), rspURL); + if (rspUUID != null) { + counter = 0; + try { + sendStillAlive(); + } catch (Exception e) { + rspUUID = null; + Logger.warn("Failed to autohost resource pack!"); } - sendStillAlive(stillAliveURL); - } catch (Exception e) { - Logger.warn("Failed to autohost resource pack!"); - e.printStackTrace(); + } else { + checkFileExistence(); + if (rspUUID == null && counter % 10 == 0) { + Logger.warn("Failed to connect to remote server to autohost the resource pack!"); + } + counter++; } } - }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 3 * 24 * 60 * 60 * 20L); + }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 60 * 20L); + } + + private static void checkFileExistence() { + initializeLink(); + if (rspUUID == null) return; + if (!sendSHA1()) uploadFile(); + } + + public static void initializeLink() { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(finalURL + "initialize"); + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String responseString = EntityUtils.toString(response.getEntity()); + rspUUID = responseString.trim(); + } catch (Exception e) { + Logger.warn("Failed to communicate with remote server!"); + } + } catch (Exception e) { + rspUUID = null; + Logger.warn("Failed remote server initialization."); + } } - public static void uploadFile(File file, String url) throws IOException { + public static void uploadFile() { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost uploadFile = new HttpPost(url); + Logger.warn("uploading file"); + HttpPost uploadFile = new HttpPost(finalURL + "upload"); - // Use FileEntity for streaming large files - FileEntity fileEntity = new FileEntity(file, ContentType.APPLICATION_OCTET_STREAM); - uploadFile.setEntity(fileEntity); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("uuid", rspUUID, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + builder.addBinaryBody("file", Mix.getFinalResourcePack(), ContentType.APPLICATION_OCTET_STREAM, Mix.getFinalResourcePack().getName()); + + uploadFile.setEntity(builder.build()); try (CloseableHttpResponse response = httpClient.execute(uploadFile)) { + } catch (Exception e) { + Logger.warn("Failed to communicate with remote server!"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static boolean sendSHA1() { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(finalURL + "sha1"); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("uuid", rspUUID, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + builder.addTextBody("sha1", Mix.getFinalSHA1(), ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + + HttpEntity entity = builder.build(); + httpPost.setEntity(entity); + + // Convert the entity to a string for logging + ByteArrayOutputStream out = new ByteArrayOutputStream(); + entity.writeTo(out); + + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { String responseString = EntityUtils.toString(response.getEntity()); - System.out.println("Response from server: " + responseString); + return Boolean.valueOf(responseString); } catch (Exception e) { - throw new RuntimeException(e); + Logger.warn("Failed to communicate with remote server!"); } + } catch (Exception e) { + } + return false; } - private static Boolean sendSHA1(String stringData, String url) throws IOException { + private static void sendStillAlive() throws IOException { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); + HttpPost httpPost = new HttpPost(finalURL + "still_alive"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.addTextBody("stringData", stringData, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + builder.addTextBody("uuid", rspUUID); httpPost.setEntity(builder.build()); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - String responseString = EntityUtils.toString(response.getEntity()); - System.out.println("Response from server: " + responseString); - return Boolean.parseBoolean(responseString.trim()); } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); - e.printStackTrace(); - return null; } } } - private static void sendStillAlive(String url) throws IOException { + public static void dataComplianceRequest() throws IOException { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); + HttpPost httpPost = new HttpPost(finalURL + "data_compliance"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.addTextBody("status", "alive", ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + builder.addTextBody("uuid", rspUUID); httpPost.setEntity(builder.build()); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - String responseString = EntityUtils.toString(response.getEntity()); - System.out.println("Response from server: " + responseString); + HttpEntity responseEntity = response.getEntity(); + + if (responseEntity != null) { + // Save the response as a zip file + File zipFile = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "data_compliance" + File.separatorChar + "data.zip"); + if (!zipFile.getParentFile().exists()) zipFile.mkdirs(); + if (zipFile.exists()) zipFile.delete(); + zipFile.createNewFile(); + try (FileOutputStream outStream = new FileOutputStream(zipFile)) { + responseEntity.writeTo(outStream); + } + InputStream inputStream = ResourcePackManager.plugin.getResource("ReadMe.md"); + + File readMe = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "data_compliance" + File.separatorChar + "ReadMe.md"); + if (!readMe.exists()) readMe.createNewFile(); + + // Copy the InputStream to the file + Files.copy(inputStream, readMe.toPath(), StandardCopyOption.REPLACE_EXISTING); + } } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); - e.printStackTrace(); } } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java index 520ffff..bc6ed70 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java @@ -20,6 +20,7 @@ public CommandManager(JavaPlugin javaPlugin) { private void registerCommands() { registerCommand(new ReloadCommand()); + registerCommand(new DataComplianceRequestCommand()); } public void registerCommand(AdvancedCommand command) { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java new file mode 100644 index 0000000..7d78ab2 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java @@ -0,0 +1,43 @@ +package com.magmaguy.resourcepackmanager.commands; + +import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.autohost.AutoHost; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.List; + +public class DataComplianceRequestCommand extends AdvancedCommand { + + public DataComplianceRequestCommand() { + super(List.of("data_compliance_request"), "Downloads a copy of all data associated to this server from the autohoster", "*", false, "/fmm data_compliance_request"); + } + + @Override + public void execute(CommandSender sender, String[] arguments) { + if (AutoHost.getRspUUID() == null) { + sender.sendMessage("[ResourcePackManager] Seems like the auto-hoster is either disabled or not working, no data is stored in remote servers because no connection to remote servers is established"); + return; + } + + new BukkitRunnable() { + @Override + public void run() { + try { + AutoHost.dataComplianceRequest(); + sender.sendMessage("[ResourcePackManager] Data compliance request completed, check ~/plugins/ResourcePackManager/data_compliance to see all data the remote server has stored for this server."); + } catch (Exception e) { + sender.sendMessage("[ResourcePackManager] Failed to request data, check console for error logs!"); + e.printStackTrace(); + } + } + }.runTaskAsynchronously(ResourcePackManager.plugin); + + } + + @Override + public List onTabComplete(CommandSender commandSender, Command command, String label, String[] args) { + return List.of(); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java new file mode 100644 index 0000000..5abc7b7 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java @@ -0,0 +1,46 @@ +package com.magmaguy.resourcepackmanager.config; + +import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.utils.ZipFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; + +public class BlueprintFolder { + private BlueprintFolder() { + } + + public static void initialize() { + Logger.warn("Creating blueprint folder"); + File blueprintDirectory = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "blueprint"); + if (!blueprintDirectory.exists()) blueprintDirectory.mkdir(); + Logger.warn("Copying image"); + File imageFile = new File(blueprintDirectory.getAbsolutePath() + File.separatorChar + "pack.png"); + if (!imageFile.exists()) { + try { + InputStream inputStream = ResourcePackManager.plugin.getResource("pack.png"); + Files.copy(inputStream, imageFile.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + Logger.warn("Copying mcmeta"); + File mcmetaFile = new File(blueprintDirectory.getAbsolutePath() + File.separatorChar + "pack.mcmeta"); + if (!mcmetaFile.exists()) { + try { + InputStream inputStream = ResourcePackManager.plugin.getResource("pack.mcmeta"); + Files.copy(inputStream, mcmetaFile.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + ZipFile.ZipUtility.zip(blueprintDirectory, blueprintDirectory.getAbsolutePath() + File.separatorChar + "blueprint.zip"); + } catch (Exception e) { + Logger.warn("Failed to zip blueprint resource pack!"); + } + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java b/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java index 7e6c8a0..024b65c 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java @@ -2,6 +2,7 @@ import com.magmaguy.resourcepackmanager.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.utils.ChatColorConverter; import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -134,6 +135,14 @@ public static List setList(List comment, File file, FileConfiguration fi setComments(fileConfiguration, key, comment); return value; } + public static String setString(File file, FileConfiguration fileConfiguration, String key, String defaultValue) { + return ChatColorConverter.convert(fileConfiguration.getString(key)); + } + public static String setString(List comments, File file, FileConfiguration fileConfiguration, String key, String defaultValue) { + String value = setString(file, fileConfiguration, key, defaultValue); + setComments(fileConfiguration, key, comments); + return value; + } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index 702aea3..c7d59ce 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -13,6 +13,10 @@ public class DefaultConfig { private static List priorityOrder; @Getter private static boolean autoHost; + @Getter + private static boolean forceResourcePack; + @Getter + private static String resourcePackPrompt; public static void initializeConfig() { file = ConfigurationEngine.fileCreator("config.yml"); @@ -31,6 +35,14 @@ public static void initializeConfig() { "These servers cost money to keep running. There is no guarantee this will be an option forever."), fileConfiguration, "autoHost", true); + forceResourcePack = ConfigurationEngine.setBoolean( + List.of("Sets whether the resource pack use will be forced to clients"), + fileConfiguration, "forceResourcePack", false); + + resourcePackPrompt = ConfigurationEngine.setString( + List.of("Sets whether the resource pack use will be forced to clients"), + file, fileConfiguration, "resourcePackPrompt", "Use recommended resource pack?"); + ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java b/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java new file mode 100644 index 0000000..bdd04bb --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java @@ -0,0 +1,4 @@ +package com.magmaguy.resourcepackmanager.datacompliance; + +public class DataCompliance { +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 608d64e..242cdc5 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -4,10 +4,7 @@ import com.google.gson.stream.JsonReader; import com.magmaguy.resourcepackmanager.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; -import com.magmaguy.resourcepackmanager.thirdparty.EliteMobs; -import com.magmaguy.resourcepackmanager.thirdparty.FreeMinecraftModels; -import com.magmaguy.resourcepackmanager.thirdparty.ModelEngine; -import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; +import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import com.magmaguy.resourcepackmanager.utils.ZipFile; import lombok.Getter; @@ -32,6 +29,8 @@ public class Mix { private static File finalResourcePack; @Getter private static String finalSHA1; + @Getter + private static byte[] finalSHA1Bytes; private Mix() { } @@ -60,6 +59,9 @@ private static boolean initializeDefaultPluginFolders() { private static void initializeThirdPartyResourcePacks() { ArrayList tempList = new ArrayList<>(); + com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager resourcePackManager = new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(); + if (resourcePackManager.isEnabled()) + tempList.add(resourcePackManager); EliteMobs eliteMobs = new EliteMobs(); if (eliteMobs.isEnabled()) tempList.add(eliteMobs); @@ -69,7 +71,15 @@ private static void initializeThirdPartyResourcePacks() { ModelEngine modelEngine = new ModelEngine(); if (modelEngine.isEnabled()) tempList.add(modelEngine); - //todo: add the rest + ItemsAdder itemsAdder = new ItemsAdder(); + if (itemsAdder.isEnabled()) + tempList.add(itemsAdder); + Nova nova = new Nova(); + if (nova.isEnabled()) + tempList.add(nova); + Oraxen oraxen = new Oraxen(); + if (oraxen.isEnabled()) + tempList.add(oraxen); thirdPartyResourcePacks = new ArrayList<>(); for (int i = 0; i < tempList.size(); i++) { for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { @@ -127,6 +137,7 @@ private static void createOutputDefaultElements() { finalResourcePack = file; try { finalSHA1 = SHA1Generator.sha1CodeString(finalResourcePack); + finalSHA1Bytes = SHA1Generator.sha1CodeByteArray(finalResourcePack); } catch (Exception e) { Logger.warn("Failed to get SHA1 from zipped resource pack!"); finalResourcePack = null; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java new file mode 100644 index 0000000..1845077 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java @@ -0,0 +1,16 @@ +package com.magmaguy.resourcepackmanager.playermanager; + +import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.resourcepackmanager.autohost.AutoHost; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; + +public class PlayerManager implements Listener { + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Logger.info("event"); + AutoHost.sendResourcePack(event.getPlayer()); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java index 3edad18..857c541 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java @@ -1,4 +1,13 @@ package com.magmaguy.resourcepackmanager.thirdparty; -public class ItemsAdder { +import java.io.File; + +public class ItemsAdder extends ThirdPartyResourcePack { + public ItemsAdder() { + super("ItemsAdder", + "ItemsAdder" + File.separatorChar + "output" + File.separatorChar + "generated.zip", + false, + false, + ""); + } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java index 0494ff6..f11caa9 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java @@ -1,4 +1,13 @@ package com.magmaguy.resourcepackmanager.thirdparty; -public class Nova { +import java.io.File; + +public class Nova extends ThirdPartyResourcePack { + public Nova() { + super("Nova", + "Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip", + false, + false, + ""); + } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java index 3d409ac..aa7e9e7 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java @@ -1,4 +1,13 @@ package com.magmaguy.resourcepackmanager.thirdparty; -public class Oraxen { -} +import java.io.File; + +public class Oraxen extends ThirdPartyResourcePack { + public Oraxen() { + super("Oraxen", + "Oraxen" + File.separatorChar + "pack" + File.separatorChar + "pack.zip", + false, + false, + ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java new file mode 100644 index 0000000..ad2cc7e --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +import java.io.File; + +public class ResourcePackManager extends ThirdPartyResourcePack { + public ResourcePackManager() { + super("ResourcePackManager", + "ResourcePackManager" + File.separatorChar + "blueprint" + File.separatorChar + "blueprint.zip", + false, + false, + "elitemobs reload"); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index 59e6c2f..113f560 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -14,10 +14,10 @@ public class ThirdPartyResourcePack implements GeneratorInterface { @Getter - private final File file; - private final boolean encrypts; - private final boolean distributes; - private final String reloadCommand; + private File file; + private boolean encrypts; + private boolean distributes; + private String reloadCommand; @Getter private boolean isEnabled; private String SHA1; @@ -31,6 +31,7 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, isEnabled = Bukkit.getPluginManager().isPluginEnabled(pluginName); if (isEnabled) Logger.info("Initializing " + pluginName + "'s resource pack"); + else return; this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); if (!file.exists()) { Logger.warn("Found " + pluginName + " but could not find resource pack at location " + file.getPath() + " ! ResourcePackManager will not be able to merge the resource pack from this plugin."); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/utils/ChatColorConverter.java b/src/main/java/com/magmaguy/resourcepackmanager/utils/ChatColorConverter.java new file mode 100644 index 0000000..cfcae6d --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/utils/ChatColorConverter.java @@ -0,0 +1,24 @@ +package com.magmaguy.resourcepackmanager.utils; + +import org.bukkit.ChatColor; + +import java.util.ArrayList; +import java.util.List; + +public class ChatColorConverter { + private ChatColorConverter() { + } + + public static String convert(String string) { + if (string == null) return ""; + return ChatColor.translateAlternateColorCodes('&', string); + } + + public static List convert(List list) { + if (list == null) return new ArrayList<>(); + List convertedList = new ArrayList<>(); + for (Object value : list) + convertedList.add(convert(value + "")); + return convertedList; + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java b/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java index c1d4edb..d0d1412 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java @@ -1,8 +1,11 @@ package com.magmaguy.resourcepackmanager.utils; +import com.magmaguy.resourcepackmanager.Logger; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -21,6 +24,28 @@ public static String sha1CodeString(File file) throws IOException, NoSuchAlgorit } } + public static String sha1CodeString(String text) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + byte[] bytes = text.getBytes(StandardCharsets.UTF_8); + byte[] resultByteArry = digest.digest(bytes); + return bytesToHexString(resultByteArry); + } catch (NoSuchAlgorithmException e) { + Logger.warn("Failed to find SHA-1 algorithm."); + } + return null; + } + + public static byte[] sha1CodeByteArray(File file) throws IOException, NoSuchAlgorithmException { + FileInputStream fileInputStream = new FileInputStream(file); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + DigestInputStream digestInputStream = new DigestInputStream(fileInputStream, digest); + byte[] bytes = new byte[1024]; + // read all file content + while (digestInputStream.read(bytes) > 0) digest = digestInputStream.getMessageDigest(); + return digest.digest(); + } + public static String bytesToHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { diff --git a/src/main/resources/ReadMe.md b/src/main/resources/ReadMe.md new file mode 100644 index 0000000..82ef310 --- /dev/null +++ b/src/main/resources/ReadMe.md @@ -0,0 +1,39 @@ +### ResourcePackManager Data Policy and Compliance + +**ResourcePackManager**, developed by MagmaGuy for the Nightbreak game studio, includes an optional auto-host feature that temporarily hosts resource pack data on a remote server. + +As of this writing, the hosted data is fully anonymous and serves the sole purpose of simplifying the distribution of resource packs to clients of servers utilizing this service. Future versions of this document may be updated to reflect any changes in data policy and other related matters. + +This system complies with: +- **Directive 2000/31/EC** of the European Parliament and of the Council of 8 June 2000 +- **Regulation (EU) 2022/2065** of the European Parliament and of the Council of 19 October 2022 + +For data hosting transparency and compliance with these and other European norms, it is possible to obtain all data related to a server via the `/resourcepackmanager data_compliance_request` command. This command packages a full copy of all files and data associated with the requesting server. + +To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\nightbreak.io` (replace `/at\ ` with `@`). However, due to the system's design, data is only retained for up to two minutes after a server using ResourcePackManager shuts down, making email requests largely unnecessary. Nonetheless, the option remains available to ensure full compliance with European norms. + +### Data Handling by ResourcePackManager and Nightbreak Servers + +1. **Resource Pack Creation** + - ResourcePackManager aggregates resource packs on your server into a single zipped file containing all custom content. + +2. **Initialization Request** + - An initialization request is sent to remote servers, creating a `.txt` file with a random UUID. This file can be obtained via the `/resourcepackmanager data_compliance_request`. + +3. **SHA1 Request** + - ResourcePackManager transmits the SHA1 code of your resource pack to the remote server, which is saved in the `.txt` file. + +4. **File Transmission** + - The zipped resource pack file is sent to the remote server, assigned the same UUID as the `.txt` file. This file can be obtained through `/resourcepackmanager data_compliance_request` and verified to be identical to the original in your output folder, as it is not modified by the Nightbreak servers. + +5. **"Still Alive" Ping** + - ResourcePackManager sends a "still alive" ping every minute, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. + - If no "still alive" ping is received for over two minutes, all data associated with that UUID (the `.txt` file and the resource pack) is deleted from the Nightbreak servers. + +### Data Policy + +- **Pseudonymous Identification:** Nightbreak assigns a random UUID to your server's files each time the server reboots, ensuring no IP address or identifiable information is stored unless users manually add such information to their resource packs. +- **No Download Logging:** Nightbreak does not log any data related to download requests by Minecraft clients. +- **No Data Sales:** Data uploaded to Nightbreak is not, has never been, and will never be sold. +- **Compliance with Takedown Requests:** Nightbreak will comply with takedown requests from both server administrators and law enforcement agencies. +- **Automatic Data Removal:** All data associated with your server is automatically removed two minutes after your server shuts down and is reuploaded on every restart for as long as ResourcePackManager is in use and using the auto-host feature. \ No newline at end of file diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..31d8f2e --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 34, + "description": "= ResourcePackManagerRSP =" + } +} \ No newline at end of file diff --git a/src/main/resources/pack.png b/src/main/resources/pack.png new file mode 100644 index 0000000000000000000000000000000000000000..485d0af91a9030be2ffd8f756a475a91ba24e287 GIT binary patch literal 22239 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 Xh#)nR5nB3o00000NkvXXu0mjfldJd4 literal 0 HcmV?d00001 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b02ba46..b57b333 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.0.0-SNAPSHOT +version: 0.0.1 api-version: 1.14 softdepend: - EliteMobs From 63d272d9529ba12ee50879473cf3938973a0bc70 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 29 Jul 2024 15:37:51 +0100 Subject: [PATCH 02/17] ResourcePackManager 0.0.2: - [New] Data retention changed to 24 hours - [New] Changed communication to avoid having players download a fresh copy of the resource pack after every server restart - [Fix] Fixed nesting of the blueprint resource pack - [New] Added MMOInventory compatibility - [New] Added ValhallaMMO compatibility - [New] Added BetterHUD compatibility - [New] Added 50000KB RSP size limit - [Tweak] Fixed up debug / warning messages First public alpha test! --- pom.xml | 42 ++++- .../magmaguy/resourcepackmanager/Logger.java | 14 -- .../ResourcePackManager.java | 26 ++- .../autohost/AutoHost.java | 77 ++++++--- .../commands/AdvancedCommand.java | 36 ---- .../commands/CommandManager.java | 104 ------------ .../DataComplianceRequestCommand.java | 22 +-- .../commands/ReloadCommand.java | 23 +-- .../config/BlueprintFolder.java | 11 +- .../config/ConfigurationEngine.java | 148 ----------------- .../config/DataConfig.java | 34 ++++ .../config/DefaultConfig.java | 25 ++- .../config/UnusedNodeHandler.java | 31 ---- .../listeners/ResourcePackGeneratedEvent.java | 16 ++ .../resourcepackmanager/mixer/Mix.java | 14 +- .../playermanager/PlayerManager.java | 2 +- .../thirdparty/BetterHUD.java | 15 ++ .../thirdparty/EliteMobs.java | 2 + .../thirdparty/FreeMinecraftModels.java | 2 + .../thirdparty/ItemsAdder.java | 2 + .../thirdparty/MMOInventory.java | 15 ++ .../thirdparty/ModelEngine.java | 2 + .../resourcepackmanager/thirdparty/Nova.java | 2 + .../thirdparty/Oraxen.java | 2 + .../thirdparty/ResourcePackManager.java | 2 + .../thirdparty/ThirdPartyResourcePack.java | 86 ++++++++-- .../thirdparty/ValhallaMMO.java | 15 ++ .../utils/SHA1Generator.java | 2 +- .../resourcepackmanager/utils/ZipFile.java | 155 ------------------ src/main/resources/ReadMe.md | 20 ++- src/main/resources/plugin.yml | 2 +- 31 files changed, 357 insertions(+), 592 deletions(-) delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/Logger.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/commands/AdvancedCommand.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/UnusedNodeHandler.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/utils/ZipFile.java diff --git a/pom.xml b/pom.xml index 239370e..f173581 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,11 @@ com.magmaguy ResourcePackManager - 0.0.1 + 0.0.2 - 22 - 22 + 17 + 17 UTF-8 @@ -22,6 +22,11 @@ central https://repo1.maven.org/maven2/ + + magmaguy-repo-releases + MagmaGuy's Repository + http://magmaguy.com:50001/releases + @@ -47,12 +52,32 @@ httpclient5 5.3.1 + + com.magmaguy + MagmaCore + 1.0 + compile + + + com.magmaguy + FreeMinecraftModels + 1.4.0 + provided + ResourcePackManager + + maven-compiler-plugin + + 17 + 17 + + + org.apache.maven.plugins maven-shade-plugin @@ -77,4 +102,15 @@ + + + magmaguy-repo-snapshots + http://magmaguy.com:50001/snapshots + + + magmaguy-repo-snapshots + MagmaGuy's Repository + http://magmaguy.com:50001/releases + + diff --git a/src/main/java/com/magmaguy/resourcepackmanager/Logger.java b/src/main/java/com/magmaguy/resourcepackmanager/Logger.java deleted file mode 100644 index 3881571..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/Logger.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.magmaguy.resourcepackmanager; - -import org.bukkit.Bukkit; - -public class Logger { - private Logger(){} - public static void warn(String message){ - Bukkit.getLogger().warning("[ResourcePackManager] " + message); - } - - public static void info(String message){ - Bukkit.getLogger().info("[ResourcePackManager] " + message); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 6fcfe8b..471567f 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -1,18 +1,24 @@ package com.magmaguy.resourcepackmanager; +import com.magmaguy.magmacore.MagmaCore; +import com.magmaguy.magmacore.command.CommandManager; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.autohost.AutoHost; -import com.magmaguy.resourcepackmanager.commands.CommandManager; +import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import com.magmaguy.resourcepackmanager.config.BlueprintFolder; +import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; +import com.magmaguy.resourcepackmanager.listeners.ResourcePackGeneratedEvent; import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; public class ResourcePackManager extends JavaPlugin { - public static Plugin plugin; + public static JavaPlugin plugin; @Override public void onEnable() { @@ -22,15 +28,21 @@ public void onEnable() { " | /\\__ \\ _/ |\\/| / _` | ' \\/ _` / _` / -_) '_|\n" + " |_|_\\|___/_| |_| |_\\__,_|_||_\\__,_\\__, \\___|_| \n" + " |___/ "); - Logger.info("ResourcePackManager v." + this.getDescription().getVersion()); + Bukkit.getLogger().info("ResourcePackManager v." + this.getDescription().getVersion()); + MagmaCore.createInstance(this); + plugin = this; - DefaultConfig.initializeConfig(); + new DefaultConfig(); + new DataConfig(); BlueprintFolder.initialize(); Mix.initialize(); - AutoHost.initialize(); - new CommandManager(this); if (DefaultConfig.isAutoHost()) Bukkit.getPluginManager().registerEvents(new PlayerManager(), this); + CommandManager commandManager = new CommandManager(this, "resourcepackmanager"); + commandManager.registerCommand(new ReloadCommand()); + commandManager.registerCommand(new DataComplianceRequestCommand()); + Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); + AutoHost.initialize(); } @Override diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index 412ca91..d7ea962 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -1,7 +1,8 @@ package com.magmaguy.resourcepackmanager.autohost; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.mixer.Mix; import lombok.Getter; @@ -13,6 +14,7 @@ import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -24,47 +26,57 @@ import java.util.UUID; public class AutoHost { - // private static final String finalURL = "http://localhost:3000/"; +// private static final String finalURL = "http://localhost:3000/"; private static final String finalURL = "http://magmaguy.com:50000/"; private static final UUID pluginRSPUUID = UUID.randomUUID(); private static BukkitTask keepAlive = null; @Getter private static String rspUUID = null; + private static boolean firstUpload = true; private AutoHost() { } public static void sendResourcePack(Player player) { if (rspUUID == null) return; - player.addResourcePack(pluginRSPUUID, finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); +// player.setResourcePack(pluginRSPUUID, finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); + player.setResourcePack(finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); + } public static void initialize() { if (!DefaultConfig.isAutoHost()) return; if (Mix.getFinalResourcePack() == null) return; - checkFileExistence(); - keepAlive = new BukkitRunnable() { - int counter = 0; - + firstUpload = true; + new BukkitRunnable() { @Override public void run() { - if (rspUUID != null) { - counter = 0; - try { - sendStillAlive(); - } catch (Exception e) { - rspUUID = null; - Logger.warn("Failed to autohost resource pack!"); + checkFileExistence(); + keepAlive = new BukkitRunnable() { + int counter = 0; + + @Override + public void run() { + if (rspUUID != null) { + counter = 0; + try { + sendStillAlive(); + } catch (Exception e) { + rspUUID = null; + Logger.warn("Failed to autohost resource pack!"); + e.printStackTrace(); + } + } else { + checkFileExistence(); + if (rspUUID == null && counter % 10 == 0) { + Logger.warn("Failed to connect to remote server to autohost the resource pack!"); + } + counter++; + } } - } else { - checkFileExistence(); - if (rspUUID == null && counter % 10 == 0) { - Logger.warn("Failed to connect to remote server to autohost the resource pack!"); - } - counter++; - } + }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 12 * 60 * 60 * 20L); } - }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 60 * 20L); + }.runTaskAsynchronously(ResourcePackManager.plugin); } private static void checkFileExistence() { @@ -76,21 +88,27 @@ private static void checkFileExistence() { public static void initializeLink() { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost(finalURL + "initialize"); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("uuid", DataConfig.getRspUUID(), ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + httpPost.setEntity(builder.build()); + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { String responseString = EntityUtils.toString(response.getEntity()); rspUUID = responseString.trim(); + DataConfig.setRspUUID(rspUUID); } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); + e.printStackTrace(); } } catch (Exception e) { rspUUID = null; Logger.warn("Failed remote server initialization."); + e.printStackTrace(); } } public static void uploadFile() { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - Logger.warn("uploading file"); HttpPost uploadFile = new HttpPost(finalURL + "upload"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); @@ -102,7 +120,15 @@ public static void uploadFile() { try (CloseableHttpResponse response = httpClient.execute(uploadFile)) { } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); + e.printStackTrace(); + return; } + Logger.info("Uploaded resource pack for automatic hosting!"); + if (firstUpload) + //Recover from a reload by sending the pack to online players + for (Player player : Bukkit.getOnlinePlayers()) + AutoHost.sendResourcePack(player); + firstUpload = false; } catch (IOException e) { throw new RuntimeException(e); } @@ -128,9 +154,10 @@ private static boolean sendSHA1() { return Boolean.valueOf(responseString); } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); + e.printStackTrace(); } } catch (Exception e) { - + e.printStackTrace(); } return false; } @@ -146,6 +173,7 @@ private static void sendStillAlive() throws IOException { try (CloseableHttpResponse response = httpClient.execute(httpPost)) { } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); + e.printStackTrace(); } } } @@ -180,6 +208,7 @@ public static void dataComplianceRequest() throws IOException { } } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); + e.printStackTrace(); } } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/AdvancedCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/AdvancedCommand.java deleted file mode 100644 index a6a651a..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/AdvancedCommand.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.magmaguy.resourcepackmanager.commands; - -import org.bukkit.command.CommandSender; - -import java.util.ArrayList; -import java.util.List; - -public abstract class AdvancedCommand { - public final List aliases; - public final String description; - public final String permission; - public final boolean onlyForPlayers; - public final boolean enabled = true; - public final String usage; - - public AdvancedCommand(List aliases, String description, String permission, boolean onlyForPlayers, String usage) { - this.aliases = aliases; - this.description = description; - this.permission = permission; - this.onlyForPlayers = onlyForPlayers; - this.usage = usage; - } - - public abstract void execute(CommandSender sender, String[] arguments); - - public abstract List onTabComplete(CommandSender commandSender, org.bukkit.command.Command command, String label, String[] args); - - protected List trimSuggestions(List suggestions, String input) { - if (input.isEmpty()) return suggestions; - List newList = new ArrayList<>(); - for (String suggestion : suggestions) - if (suggestion.contains(input)) - newList.add(suggestion); - return newList; - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java deleted file mode 100644 index bc6ed70..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/CommandManager.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.magmaguy.resourcepackmanager.commands; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -import java.util.ArrayList; -import java.util.List; - -public class CommandManager implements CommandExecutor, TabCompleter { - public final List commands = new ArrayList<>(); - - public CommandManager(JavaPlugin javaPlugin) { - javaPlugin.getCommand("resourcepackmanager").setExecutor(this); - registerCommands(); - } - - private void registerCommands() { - registerCommand(new ReloadCommand()); - registerCommand(new DataComplianceRequestCommand()); - } - - public void registerCommand(AdvancedCommand command) { - commands.add(command); - } - - public void unregisterCommand(Command command) { - commands.remove(command); - } - - - private void sendMessage(CommandSender commandSender, String message) { - commandSender.sendMessage("[ResourcePackManager] " + message); - } - - @Override - public boolean onCommand(CommandSender commandSender, Command cmd, String label, String[] args) { - if (args.length == 0) { - sendMessage(commandSender, "Valid commands:"); - commands.forEach(command -> commandSender.sendMessage(command.usage)); - return true; - } - - for (AdvancedCommand command : commands) { - // We don't want to execute other commands or ones that are disabled - if (!(command.aliases.contains(args[0]) && command.enabled)) { - continue; - } - - if (command.onlyForPlayers && !(commandSender instanceof Player)) { - // Must be a player - commandSender.sendMessage("[ResourcePackManager] This command must be run as a player!"); - return false; - } - - if (!((commandSender.hasPermission(command.permission) || - command.permission.equalsIgnoreCase("") || - command.permission.equalsIgnoreCase("resourcepackmanager.")) && - command.enabled)) { - // No permissions - commandSender.sendMessage("[ResourcePackManager] You do not have the permission to run this command!"); - return false; - } - - command.execute(commandSender, args); - return true; - } - // Unknown command message - commandSender.sendMessage("[ResourcePackManager] Unknown command!"); - return false; - } - - @Override - public List onTabComplete(CommandSender commandSender, Command cmd, String label, String[] args) { - // Handle the tab completion if it's a sub-command. - if (args.length == 1) { - List result = new ArrayList<>(); - for (AdvancedCommand command : commands) { - for (String alias : command.aliases) { - if (alias.toLowerCase().startsWith(args[0].toLowerCase()) && ( - command.enabled && (commandSender.hasPermission(command.permission) - || command.permission.equalsIgnoreCase("") || command.permission - .equalsIgnoreCase("resourcepackmanager.")))) { - result.add(alias); - } - } - } - return result; - } - - // Let the sub-command handle the tab completion - for (AdvancedCommand command : commands) { - if (command.aliases.contains(args[0]) && (command.enabled && ( - commandSender.hasPermission(command.permission) || command.permission.equalsIgnoreCase("") - || command.permission.equalsIgnoreCase("resourcepackmanager.")))) { - return command.onTabComplete(commandSender, cmd, label, args); - } - } - return null; - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java index 7d78ab2..b736562 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java @@ -1,5 +1,8 @@ package com.magmaguy.resourcepackmanager.commands; +import com.magmaguy.magmacore.command.AdvancedCommand; +import com.magmaguy.magmacore.command.CommandData; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.autohost.AutoHost; import org.bukkit.command.Command; @@ -11,13 +14,16 @@ public class DataComplianceRequestCommand extends AdvancedCommand { public DataComplianceRequestCommand() { - super(List.of("data_compliance_request"), "Downloads a copy of all data associated to this server from the autohoster", "*", false, "/fmm data_compliance_request"); + super(List.of("data_compliance_request")); + setDescription("Downloads a copy of all data associated to this server from the autohoster"); + setPermission("resourcepackmanager.*"); + setUsage("/fmm data_compliance_request"); } @Override - public void execute(CommandSender sender, String[] arguments) { + public void execute(CommandData commandData) { if (AutoHost.getRspUUID() == null) { - sender.sendMessage("[ResourcePackManager] Seems like the auto-hoster is either disabled or not working, no data is stored in remote servers because no connection to remote servers is established"); + Logger.sendMessage(commandData.getCommandSender(), "Seems like the auto-hoster is either disabled or not working, no data is stored in remote servers because no connection to remote servers is established"); return; } @@ -26,18 +32,12 @@ public void execute(CommandSender sender, String[] arguments) { public void run() { try { AutoHost.dataComplianceRequest(); - sender.sendMessage("[ResourcePackManager] Data compliance request completed, check ~/plugins/ResourcePackManager/data_compliance to see all data the remote server has stored for this server."); + Logger.sendMessage(commandData.getCommandSender(), "Data compliance request completed, check ~/plugins/ResourcePackManager/data_compliance to see all data the remote server has stored for this server."); } catch (Exception e) { - sender.sendMessage("[ResourcePackManager] Failed to request data, check console for error logs!"); + Logger.sendMessage(commandData.getCommandSender(), "Failed to request data, check console for error logs!"); e.printStackTrace(); } } }.runTaskAsynchronously(ResourcePackManager.plugin); - - } - - @Override - public List onTabComplete(CommandSender commandSender, Command command, String label, String[] args) { - return List.of(); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java index 7da4f08..51dfa2e 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java @@ -1,7 +1,10 @@ package com.magmaguy.resourcepackmanager.commands; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.command.AdvancedCommand; +import com.magmaguy.magmacore.command.CommandData; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import java.util.Collections; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -9,22 +12,22 @@ public class ReloadCommand extends AdvancedCommand { public ReloadCommand() { - super(List.of("reload"), "Reloads the plugin", "*", false, "/fmm reload"); + super(List.of("reload")); + setDescription("Reloads the plugin"); + setPermission("resourcepackmanager.*"); + setUsage("/fmm reload"); } public static void reloadPlugin(CommandSender sender) { ResourcePackManager.plugin.onDisable(); ResourcePackManager.plugin.onEnable(); - sender.sendMessage("[ResourcePackManager] Reloaded plugin!"); + Logger.sendMessage(sender, "Reloaded the plugin!"); } @Override - public void execute(CommandSender sender, String[] arguments) { - reloadPlugin(sender); - } - - @Override - public List onTabComplete(CommandSender commandSender, Command command, String label, String[] args) { - return null; + public void execute(CommandData commandData) { + ResourcePackManager.plugin.onDisable(); + ResourcePackManager.plugin.onEnable(); + Logger.sendMessage(commandData.getCommandSender(), "Reloaded the plugin!"); } } \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java index 5abc7b7..3a8c9f4 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java @@ -1,8 +1,8 @@ package com.magmaguy.resourcepackmanager.config; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; -import com.magmaguy.resourcepackmanager.utils.ZipFile; import java.io.File; import java.io.IOException; @@ -14,10 +14,10 @@ private BlueprintFolder() { } public static void initialize() { - Logger.warn("Creating blueprint folder"); + Logger.info("Creating blueprint folder"); File blueprintDirectory = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "blueprint"); if (!blueprintDirectory.exists()) blueprintDirectory.mkdir(); - Logger.warn("Copying image"); + Logger.info("Copying image"); File imageFile = new File(blueprintDirectory.getAbsolutePath() + File.separatorChar + "pack.png"); if (!imageFile.exists()) { try { @@ -27,12 +27,13 @@ public static void initialize() { e.printStackTrace(); } } - Logger.warn("Copying mcmeta"); + Logger.info("Copying mcmeta"); File mcmetaFile = new File(blueprintDirectory.getAbsolutePath() + File.separatorChar + "pack.mcmeta"); if (!mcmetaFile.exists()) { try { InputStream inputStream = ResourcePackManager.plugin.getResource("pack.mcmeta"); Files.copy(inputStream, mcmetaFile.toPath()); + inputStream.close(); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java b/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java deleted file mode 100644 index 024b65c..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/ConfigurationEngine.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.magmaguy.resourcepackmanager.config; - -import com.magmaguy.resourcepackmanager.Logger; -import com.magmaguy.resourcepackmanager.ResourcePackManager; -import com.magmaguy.resourcepackmanager.utils.ChatColorConverter; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.List; - -public class ConfigurationEngine { - - public static File fileCreator(String path, String fileName) { - File file = new File(ResourcePackManager.plugin.getDataFolder().getPath() + "/" + path + "/", fileName); - return fileCreator(file); - } - - public static File fileCreator(String fileName) { - File file = new File(ResourcePackManager.plugin.getDataFolder().getPath(), fileName); - return fileCreator(file); - } - - public static File fileCreator(File file) { - - if (!file.exists()) - try { - file.getParentFile().mkdirs(); - file.createNewFile(); - } catch (IOException ex) { - Bukkit.getLogger().warning("[EliteMobs] Error generating the plugin file: " + file.getName()); - } - - return file; - - } - - public static FileConfiguration fileConfigurationCreator(File file) { - try { - return YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)); - } catch (Exception exception) { - Logger.warn("Failed to read configuration from file " + file.getName()); - return null; - } - } - - public static void fileSaverCustomValues(FileConfiguration fileConfiguration, File file) { - fileConfiguration.options().copyDefaults(true); - - try { - fileConfiguration.save(file); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - public static void fileSaverOnlyDefaults(FileConfiguration fileConfiguration, File file) { - fileConfiguration.options().copyDefaults(true); - UnusedNodeHandler.clearNodes(fileConfiguration); - - try { - fileConfiguration.save(file); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - private static void setComments(FileConfiguration fileConfiguration, String key, List comments) { - fileConfiguration.setComments(key, comments); - } - - public static Boolean setBoolean(FileConfiguration fileConfiguration, String key, boolean defaultValue) { - fileConfiguration.addDefault(key, defaultValue); - return fileConfiguration.getBoolean(key); - } - - public static Boolean setBoolean(List comments, FileConfiguration fileConfiguration, String key, boolean defaultValue) { - boolean value = setBoolean(fileConfiguration, key, defaultValue); - setComments(fileConfiguration, key, comments); - return value; - } - - - public static int setInt(FileConfiguration fileConfiguration, String key, int defaultValue) { - fileConfiguration.addDefault(key, defaultValue); - return fileConfiguration.getInt(key); - } - - public static int setInt(List comments, FileConfiguration fileConfiguration, String key, int defaultValue) { - int value = setInt(fileConfiguration, key, defaultValue); - setComments(fileConfiguration, key, comments); - return value; - } - - public static double setDouble(FileConfiguration fileConfiguration, String key, double defaultValue) { - fileConfiguration.addDefault(key, defaultValue); - return fileConfiguration.getDouble(key); - } - - public static double setDouble(List comments, FileConfiguration fileConfiguration, String key, double defaultValue) { - double value = setDouble(fileConfiguration, key, defaultValue); - setComments(fileConfiguration, key, comments); - return value; - } - - public static boolean writeValue(Object value, File file, FileConfiguration fileConfiguration, String path) { - fileConfiguration.set(path, value); - try { - fileSaverCustomValues(fileConfiguration, file); - } catch (Exception exception) { - Logger.warn("Failed to write value for " + path + " in file " + file.getName()); - return false; - } - return true; - } - - public static void removeValue(File file, FileConfiguration fileConfiguration, String path) { - writeValue(null, file, fileConfiguration, path); - } - - public static List setList(File file, FileConfiguration fileConfiguration, String key, List defaultValue) { - fileConfiguration.addDefault(key, defaultValue); - return fileConfiguration.getList(key); - } - - public static List setList(List comment, File file, FileConfiguration fileConfiguration, String key, List defaultValue) { - List value = setList(file, fileConfiguration, key, defaultValue); - setComments(fileConfiguration, key, comment); - return value; - } - public static String setString(File file, FileConfiguration fileConfiguration, String key, String defaultValue) { - return ChatColorConverter.convert(fileConfiguration.getString(key)); - } - - public static String setString(List comments, File file, FileConfiguration fileConfiguration, String key, String defaultValue) { - String value = setString(file, fileConfiguration, key, defaultValue); - setComments(fileConfiguration, key, comments); - return value; - } - -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java new file mode 100644 index 0000000..919d8e0 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java @@ -0,0 +1,34 @@ +package com.magmaguy.resourcepackmanager.config; + +import com.magmaguy.magmacore.config.ConfigurationFile; +import com.magmaguy.magmacore.util.Logger; + +public class DataConfig extends ConfigurationFile { + private static DataConfig instance = null; + + public DataConfig() { + super("data.yml"); + instance = this; + } + + public static String getRspUUID() { + String uuid = instance.getFileConfiguration().getString("uuid"); + if (uuid == null) uuid = ""; + return uuid; + } + + public static void setRspUUID(String rspUUID) { + instance.getFileConfiguration().set("uuid", rspUUID); + try { + instance.getFileConfiguration().save(instance.file); + } catch (Exception e) { + Logger.warn("Failed to save uuid!"); + e.printStackTrace(); + } + } + + @Override + public void initializeValues() { + + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index c7d59ce..e9f3fdd 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -1,14 +1,13 @@ package com.magmaguy.resourcepackmanager.config; +import com.magmaguy.magmacore.config.ConfigurationEngine; +import com.magmaguy.magmacore.config.ConfigurationFile; import lombok.Getter; -import org.bukkit.configuration.file.FileConfiguration; -import java.io.File; import java.util.List; -public class DefaultConfig { - private static File file = null; - private static FileConfiguration fileConfiguration = null; +public class DefaultConfig extends ConfigurationFile { + @Getter private static List priorityOrder; @Getter @@ -18,16 +17,18 @@ public class DefaultConfig { @Getter private static String resourcePackPrompt; - public static void initializeConfig() { - file = ConfigurationEngine.fileCreator("config.yml"); - fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file); + public DefaultConfig() { + super("config.yml"); + } + @Override + public void initializeValues() { priorityOrder = ConfigurationEngine.setList( List.of( "Sets the list, from highest priority (top) to lowest priority (bottom), in which the resource" + " packs will automatically resolve merge conflicts.", "The defaults use plugin names. If you manually added your own resource pack in the mixer folder to be merged in, add its exact filename, including .zip in the name"), - file, fileConfiguration, "priorityOrder", + fileConfiguration, "priorityOrder", List.of("ResourcePackManager", "EliteMobs", "FreeMinecraftModels", "ModelEngine", "ItemsAdder", "Nova", "Oraxen")); autoHost = ConfigurationEngine.setBoolean( @@ -41,10 +42,6 @@ public static void initializeConfig() { resourcePackPrompt = ConfigurationEngine.setString( List.of("Sets whether the resource pack use will be forced to clients"), - file, fileConfiguration, "resourcePackPrompt", "Use recommended resource pack?"); - - ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file); + fileConfiguration, "resourcePackPrompt", "Use recommended resource pack?"); } - - } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/UnusedNodeHandler.java b/src/main/java/com/magmaguy/resourcepackmanager/config/UnusedNodeHandler.java deleted file mode 100644 index e05eb13..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/UnusedNodeHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.magmaguy.resourcepackmanager.config; - -import com.magmaguy.resourcepackmanager.Logger; -import org.bukkit.Bukkit; -import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.file.FileConfiguration; - -public class UnusedNodeHandler { - - private UnusedNodeHandler() { - } - - public static Configuration clearNodes(FileConfiguration configuration) { - - for (String actual : configuration.getKeys(false)) { - boolean keyExists = false; - for (String defaults : configuration.getDefaults().getKeys(true)) - if (actual.equals(defaults)) { - keyExists = true; - break; - } - - if (!keyExists) { - configuration.set(actual, null); - Bukkit.getLogger().warning(actual); - Logger.warn("Deleting unused config values."); - } - } - return configuration; - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java new file mode 100644 index 0000000..d92814e --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java @@ -0,0 +1,16 @@ +package com.magmaguy.resourcepackmanager.listeners; + +import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; +import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class ResourcePackGeneratedEvent implements Listener { + @EventHandler + public void onResourcePackGenerated(ResourcePackGenerationEvent event) { + ReloadCommand.reloadPlugin(Bukkit.getConsoleSender()); + Logger.sendMessage(Bukkit.getConsoleSender(), "Resource pack regenerated!"); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 242cdc5..956692f 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -2,11 +2,11 @@ import com.google.gson.*; import com.google.gson.stream.JsonReader; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; -import com.magmaguy.resourcepackmanager.utils.ZipFile; import lombok.Getter; import java.io.File; @@ -15,12 +15,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributeView; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.TimeUnit; public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; @@ -80,6 +76,12 @@ private static void initializeThirdPartyResourcePacks() { Oraxen oraxen = new Oraxen(); if (oraxen.isEnabled()) tempList.add(oraxen); + BetterHUD betterHUD = new BetterHUD(); + if (betterHUD.isEnabled()) + tempList.add(betterHUD); + ValhallaMMO valhallaMMO = new ValhallaMMO(); + if (valhallaMMO.isEnabled()) + tempList.add(valhallaMMO); thirdPartyResourcePacks = new ArrayList<>(); for (int i = 0; i < tempList.size(); i++) { for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java index 1845077..d8e67ae 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java @@ -1,6 +1,6 @@ package com.magmaguy.resourcepackmanager.playermanager; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.autohost.AutoHost; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java new file mode 100644 index 0000000..22602fe --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +import java.io.File; + +public class BetterHUD extends ThirdPartyResourcePack { + public BetterHUD() { + super("BetterHUD", + "BetterHUD" + File.separatorChar + "build.zip", + true, + false, + true, + true, + "betterhud reload"); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java index 6a69bb7..f4ca084 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java @@ -10,6 +10,8 @@ public EliteMobs() { "EliteMobs" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip", false, false, + true, + true, "elitemobs reload"); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java index 7697c26..6b790a8 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java @@ -8,6 +8,8 @@ public FreeMinecraftModels() { "FreeMinecraftModels" + File.separatorChar + "output" + File.separatorChar + "FreeMinecraftModels.zip", false, false, + true, + true, "freeminecraftmodels reload"); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java index 857c541..a4b21e5 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java @@ -8,6 +8,8 @@ public ItemsAdder() { "ItemsAdder" + File.separatorChar + "output" + File.separatorChar + "generated.zip", false, false, + true, + true, ""); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java new file mode 100644 index 0000000..505dc3b --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +import java.io.File; + +public class MMOInventory extends ThirdPartyResourcePack { + public MMOInventory() { + super("MMOInventory", + "https://www.dropbox.com/s/1lftxmzh0q4b5yu/mmoinv_rp_3.zip?dl=1", + false, + false, + true, + false, + ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java index e3125e9..1760ba1 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java @@ -8,6 +8,8 @@ public ModelEngine() { "ModelEngine" + File.separatorChar + "resource pack.zip", false, false, + true, + true, "meg reload"); } } \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java index f11caa9..13a017c 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java @@ -8,6 +8,8 @@ public Nova() { "Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip", false, false, + true, + true, ""); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java index aa7e9e7..b828c09 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java @@ -8,6 +8,8 @@ public Oraxen() { "Oraxen" + File.separatorChar + "pack" + File.separatorChar + "pack.zip", false, false, + true, + true, ""); } } \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java index ad2cc7e..59ad392 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java @@ -8,6 +8,8 @@ public ResourcePackManager() { "ResourcePackManager" + File.separatorChar + "blueprint" + File.separatorChar + "blueprint.zip", false, false, + true, + true, "elitemobs reload"); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index 113f560..6fb2855 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -1,22 +1,32 @@ package com.magmaguy.resourcepackmanager.thirdparty; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.HttpEntity; import org.bukkit.Bukkit; import java.io.File; +import java.io.FileOutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; public class ThirdPartyResourcePack implements GeneratorInterface { @Getter - private File file; + private File file = null; + private String url; private boolean encrypts; private boolean distributes; + private boolean zips; + private boolean local; private String reloadCommand; @Getter private boolean isEnabled; @@ -26,13 +36,19 @@ public class ThirdPartyResourcePack implements GeneratorInterface { private File mixerResourcePack = null; @Getter private int priority = -1; + private final String pluginName; - public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, boolean distributes, String reloadCommand) { + public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, boolean distributes, boolean zips, boolean local, String reloadCommand) { + this.pluginName = pluginName; isEnabled = Bukkit.getPluginManager().isPluginEnabled(pluginName); if (isEnabled) Logger.info("Initializing " + pluginName + "'s resource pack"); else return; - this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); + this.local = local; + if (local) + this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); + else + this.url = path; if (!file.exists()) { Logger.warn("Found " + pluginName + " but could not find resource pack at location " + file.getPath() + " ! ResourcePackManager will not be able to merge the resource pack from this plugin."); isEnabled = false; @@ -40,7 +56,8 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, this.encrypts = encrypts; this.distributes = distributes; this.reloadCommand = reloadCommand; - if (isEnabled) SHA1 = getSHA1(file); + this.zips = zips; + if (isEnabled && local) SHA1 = getSHA1(file); process(); if (DefaultConfig.getPriorityOrder().contains(pluginName)) priority = DefaultConfig.getPriorityOrder().indexOf(pluginName); @@ -48,15 +65,17 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, public void process() { if (!isEnabled) return; - if (mixerCloneExists()) { - if (getSHA1(new File(getTarget().toUri())).equals(SHA1)) { - mixerResourcePack = getTarget().toFile(); - return; - } else { - Logger.info("Clearing outdated resource pack in " + getTarget()); - getTarget().toFile().delete(); + if (local && zips) { + if (mixerCloneExists()) { + if (getSHA1(new File(getTarget().toUri())).equals(SHA1)) { + mixerResourcePack = getTarget().toFile(); + return; + } else { + Logger.info("Clearing outdated resource pack in " + getTarget()); + getTarget().toFile().delete(); + } } - } + } else if (local && mixerCloneExists()) getTarget().toFile().delete(); if (encrypts) decrypt(); if (distributes) unpublish(); cloneResourcePackFile(); @@ -83,15 +102,48 @@ public void unpublish() { @Override public void cloneResourcePackFile() { + if (local) cloneLocalRSP(); + else cloneRemoteRSP(); + resourcePackUpdated = true; + } + + private void cloneLocalRSP() { try { - Logger.info("Cloning resource pack from " + file.toPath()); - mixerResourcePack = Files.copy(Path.of(file.getAbsolutePath()), Path.of(getTarget().toAbsolutePath().toString()), StandardCopyOption.REPLACE_EXISTING).toFile(); + if (zips) { + Logger.info("Cloning resource pack from " + file.toPath()); + mixerResourcePack = Files.copy(Path.of(file.getAbsolutePath()), Path.of(getTarget().toAbsolutePath().toString()), StandardCopyOption.REPLACE_EXISTING).toFile(); + } else { + if (mixerCloneExists()) getTarget().toFile().delete(); + Logger.info("Cloning resource pack from " + file.toPath()); + ZipFile.zip(file, getTarget().toString()); + } } catch (Exception e) { Logger.warn("Failed to clone resource pack from " + file.getPath() + " to the mixer folder!"); e.printStackTrace(); } + } - resourcePackUpdated = true; + private void cloneRemoteRSP() { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + HttpEntity responseEntity = response.getEntity(); + + if (responseEntity != null) { + // Save the response as a zip file + File zipFile = getTarget().toFile(); + if (zipFile.exists()) zipFile.delete(); + zipFile.createNewFile(); + try (FileOutputStream outStream = new FileOutputStream(zipFile)) { + responseEntity.writeTo(outStream); + } + } + } catch (Exception e) { + Logger.warn("Failed to communicate with remote server when downloading resource pack for plugin " + pluginName + "!"); + } + } catch (Exception e) { + Logger.warn("Failed to connect to url " + url + " to download resource pack for plugin " + pluginName); + } } @Override @@ -104,6 +156,6 @@ private boolean mixerCloneExists() { } private Path getTarget() { - return Path.of(ResourcePackManager.plugin.getDataFolder().toString(), "mixer", file.getName()); + return Path.of(ResourcePackManager.plugin.getDataFolder().toString(), "mixer", file.getName().endsWith(".zip") ? file.getName() : file.getName() + ".zip"); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java new file mode 100644 index 0000000..d593d41 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +import java.io.File; + +public class ValhallaMMO extends ThirdPartyResourcePack { + public ValhallaMMO() { + super("ValhallaMMO", + "Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip", + false, + false, + true, + true, + ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java b/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java index d0d1412..5cd8649 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/utils/SHA1Generator.java @@ -1,6 +1,6 @@ package com.magmaguy.resourcepackmanager.utils; -import com.magmaguy.resourcepackmanager.Logger; +import com.magmaguy.magmacore.util.Logger; import java.io.File; import java.io.FileInputStream; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/utils/ZipFile.java b/src/main/java/com/magmaguy/resourcepackmanager/utils/ZipFile.java deleted file mode 100644 index 757dee4..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/utils/ZipFile.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.magmaguy.resourcepackmanager.utils; - -import com.magmaguy.resourcepackmanager.Logger; - -import java.io.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class ZipFile { - private ZipFile() { - } - - public static boolean zip(File directory, String targetZipPath) { - if (!directory.exists()) { - Logger.warn("Failed to zip directory " + directory.getPath() + " because it does not exist!"); - return false; - } - - try { - ZipUtility.zip(directory, targetZipPath); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - public static File unzip(File zippedFile, File destinationUnzippedFile) throws IOException { - byte[] buffer = new byte[1024]; - ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zippedFile)); - ZipEntry zipEntry = zipInputStream.getNextEntry(); - while (zipEntry != null) { - File newFile = newFile(destinationUnzippedFile, zipEntry); - if (zipEntry.isDirectory()) { - if (!newFile.isDirectory() && !newFile.mkdirs()) { - throw new IOException("Failed to create directory " + newFile); - } - } else { - // Fix for Windows-created archives - File parent = newFile.getParentFile(); - if (!parent.isDirectory() && !parent.mkdirs()) { - throw new IOException("Failed to create directory " + parent); - } - - // Write file content - FileOutputStream fileOutputStream = new FileOutputStream(newFile); - int len; - while ((len = zipInputStream.read(buffer)) > 0) { - fileOutputStream.write(buffer, 0, len); - } - fileOutputStream.close(); - } - newFile.setLastModified(zipEntry.getTime()); - zipEntry = zipInputStream.getNextEntry(); - } - zipInputStream.closeEntry(); - zipInputStream.close(); - return destinationUnzippedFile; - } - - private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { - File destFile = new File(destinationDir, zipEntry.getName()); - - String destDirPath = destinationDir.getCanonicalPath(); - String destFilePath = destFile.getCanonicalPath(); - - if (!destFilePath.startsWith(destDirPath + File.separatorChar)) { - throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); - } - - return destFile; - } - - public static class ZipUtility { - /** - * A constant for buffer size used to read/write data - */ - private static final int BUFFER_SIZE = 4096; - - /** - * Compresses a list of files to a destination zip file - * - * @param file File to zip - * @param destZipFile The path of the destination zip file - * @throws FileNotFoundException - * @throws IOException - */ - public static void zip(File file, String destZipFile) throws FileNotFoundException, IOException { - FileOutputStream fileOutputStream = new FileOutputStream(destZipFile); - ZipOutputStream zos = new ZipOutputStream(fileOutputStream); - // This slight tweak avoids making the directory zipped be in the zipped file when what we are looking for is to - // zip the contents of the directory, outside of the directory itself - if (file.isDirectory()) { - for (File file1 : file.listFiles()) { - if (file1.isDirectory()) - zipDirectory(file1, file1.getName(), zos); - else - zipFile(file1, zos); - } - } else { - zipFile(file, zos); - } - zos.flush(); - zos.close(); - fileOutputStream.close(); - } - - /** - * Adds a directory to the current zip output stream - * - * @param folder the directory to be added - * @param parentFolder the path of parent directory - * @param zos the current zip output stream - * @throws FileNotFoundException - * @throws IOException - */ - private static void zipDirectory(File folder, String parentFolder, ZipOutputStream zos) throws FileNotFoundException, IOException { - for (File file : folder.listFiles()) { - if (file.isDirectory()) { - zipDirectory(file, parentFolder + "/" + file.getName(), zos); - continue; - } - ZipEntry zipEntry = new ZipEntry(parentFolder + "/" + file.getName()); - zippedySplit(zos, file, zipEntry); - } - } - - /** - * Adds a file to the current zip output stream - * - * @param file the file to be added - * @param zos the current zip output stream - * @throws FileNotFoundException - * @throws IOException - */ - private static void zipFile(File file, ZipOutputStream zos) throws FileNotFoundException, IOException { - ZipEntry zipEntry = new ZipEntry(file.getName()); - zippedySplit(zos, file, zipEntry); - } - - private static void zippedySplit(ZipOutputStream zos, File file, ZipEntry zipEntry) throws IOException { - zipEntry.setTime(0L); - zos.putNextEntry(zipEntry); - BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); - byte[] bytesIn = new byte[BUFFER_SIZE]; - int read; - while ((read = bis.read(bytesIn)) != -1) { - zos.write(bytesIn, 0, read); - } - zos.closeEntry(); - bis.close(); - } - } -} diff --git a/src/main/resources/ReadMe.md b/src/main/resources/ReadMe.md index 82ef310..d24b2df 100644 --- a/src/main/resources/ReadMe.md +++ b/src/main/resources/ReadMe.md @@ -10,7 +10,7 @@ This system complies with: For data hosting transparency and compliance with these and other European norms, it is possible to obtain all data related to a server via the `/resourcepackmanager data_compliance_request` command. This command packages a full copy of all files and data associated with the requesting server. -To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\nightbreak.io` (replace `/at\ ` with `@`). However, due to the system's design, data is only retained for up to two minutes after a server using ResourcePackManager shuts down, making email requests largely unnecessary. Nonetheless, the option remains available to ensure full compliance with European norms. +To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\nightbreak.io` (replace `/at\ ` with `@`). However, due to the system's design, data is only retained for up to 24h after a server using ResourcePackManager shuts down, making email requests largely unnecessary. Nonetheless, the option remains available to ensure full compliance with European norms. ### Data Handling by ResourcePackManager and Nightbreak Servers @@ -27,8 +27,8 @@ To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\ - The zipped resource pack file is sent to the remote server, assigned the same UUID as the `.txt` file. This file can be obtained through `/resourcepackmanager data_compliance_request` and verified to be identical to the original in your output folder, as it is not modified by the Nightbreak servers. 5. **"Still Alive" Ping** - - ResourcePackManager sends a "still alive" ping every minute, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. - - If no "still alive" ping is received for over two minutes, all data associated with that UUID (the `.txt` file and the resource pack) is deleted from the Nightbreak servers. + - ResourcePackManager sends a "still alive" ping every 12 hours, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. + - If no "still alive" ping is received for over 24 hours, all data associated with that UUID (the `.txt` file and the resource pack) is deleted from the Nightbreak servers. ### Data Policy @@ -36,4 +36,16 @@ To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\ - **No Download Logging:** Nightbreak does not log any data related to download requests by Minecraft clients. - **No Data Sales:** Data uploaded to Nightbreak is not, has never been, and will never be sold. - **Compliance with Takedown Requests:** Nightbreak will comply with takedown requests from both server administrators and law enforcement agencies. -- **Automatic Data Removal:** All data associated with your server is automatically removed two minutes after your server shuts down and is reuploaded on every restart for as long as ResourcePackManager is in use and using the auto-host feature. \ No newline at end of file +- **Automatic Data Removal:** All data associated with your server is automatically removed 24 hours after your server shuts down and is reuploaded on every restart for as long as ResourcePackManager is in use and using the auto-host feature. + +### Terms of service + +As of writing this, the hosting service is provided for free for all users of ResourcePackManager. + +It is the user's responsibility to ensure that the data uploaded to servers is not illegal and complies with any Mojang TOS as defined in their EULA. + +Abusing the service to host material other than resource packages may result in a permanent denial of service for the offending IP. + +The service may, at any time, cease or be modified in such a way that makes old versions unable to connect to it. + +We reserve the right to unilaterally terminate this service at any time and for any reason. \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b57b333..c7dbc86 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 0.0.1 +version: 0.0.2 api-version: 1.14 softdepend: - EliteMobs From 4527e36ef6be2760c734de6535e17f22f6d6ce6a Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 2 Aug 2024 13:02:47 +0100 Subject: [PATCH 03/17] ResourcePackManager 1.0.0: - [New] Data retention changed to 24 hours - [New] Changed communication to avoid having players download a fresh copy of the resource pack after every server restart - [New] Moved core features to MagmaCore - Redid all the commands - Redid all the configuration systems - [Fix] Fixed nesting of the blueprint resource pack - [New] Added MMOInventory compatibility - [New] Added ValhallaMMO compatibility - [New] Added BetterHUD compatibility - [New] Added 50000KB RSP size limit - [Tweak] Fixed up debug / warning messages First public alpha test! - [Fix] Fixed issue where events would not get unregistered correctly --- pom.xml | 4 ++-- .../magmaguy/resourcepackmanager/ResourcePackManager.java | 6 ++++-- .../magmaguy/resourcepackmanager/config/DefaultConfig.java | 2 +- .../listeners/ResourcePackGeneratedEvent.java | 2 -- src/main/resources/plugin.yml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index f173581..7b92717 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 0.0.2 + 1.0.0 17 @@ -55,7 +55,7 @@ com.magmaguy MagmaCore - 1.0 + 1.7 compile diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 471567f..b028f25 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -13,7 +13,7 @@ import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; public class ResourcePackManager extends JavaPlugin { @@ -41,13 +41,15 @@ public void onEnable() { CommandManager commandManager = new CommandManager(this, "resourcepackmanager"); commandManager.registerCommand(new ReloadCommand()); commandManager.registerCommand(new DataComplianceRequestCommand()); - Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); + if (Bukkit.getPluginManager().isPluginEnabled("FreeMinecraftModels")) + Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); AutoHost.initialize(); } @Override public void onDisable() { Logger.info("Disabling ResourcePackManager"); + HandlerList.unregisterAll(this); AutoHost.shutdown(); } } \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index e9f3fdd..07574e9 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -29,7 +29,7 @@ public void initializeValues() { " packs will automatically resolve merge conflicts.", "The defaults use plugin names. If you manually added your own resource pack in the mixer folder to be merged in, add its exact filename, including .zip in the name"), fileConfiguration, "priorityOrder", - List.of("ResourcePackManager", "EliteMobs", "FreeMinecraftModels", "ModelEngine", "ItemsAdder", "Nova", "Oraxen")); + List.of("ResourcePackManager", "EliteMobs", "FreeMinecraftModels", "ModelEngine", "ItemsAdder", "Nova", "Oraxen", "BetterHUD", "ValhallaMMO", "MMOInventory")); autoHost = ConfigurationEngine.setBoolean( List.of("Automatically host the resource pack on MagmaGuy's servers", diff --git a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java index d92814e..07a5d6b 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java @@ -1,7 +1,6 @@ package com.magmaguy.resourcepackmanager.listeners; import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; -import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; @@ -11,6 +10,5 @@ public class ResourcePackGeneratedEvent implements Listener { @EventHandler public void onResourcePackGenerated(ResourcePackGenerationEvent event) { ReloadCommand.reloadPlugin(Bukkit.getConsoleSender()); - Logger.sendMessage(Bukkit.getConsoleSender(), "Resource pack regenerated!"); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c7dbc86..a4c9fbc 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 0.0.2 +version: 1.0.0 api-version: 1.14 softdepend: - EliteMobs From 76ad4b3318d34b38eebebc6526e1270f8e933362 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 2 Aug 2024 13:12:45 +0100 Subject: [PATCH 04/17] - Added Bstats --- pom.xml | 11 +++++++++++ .../resourcepackmanager/ResourcePackManager.java | 3 +++ 2 files changed, 14 insertions(+) diff --git a/pom.xml b/pom.xml index 7b92717..6dbd6a2 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,13 @@ 1.4.0 provided + + + org.bstats + bstats-bukkit + 3.0.2 + compile + @@ -95,6 +102,10 @@ org.apache.hc com.magmaguy.resourcepackmanager.org.apache.hc + + org.bstats + com.magmaguy.freeminecraftmodels + diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index b028f25..6b1fe03 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -1,5 +1,6 @@ package com.magmaguy.resourcepackmanager; +import com.magmaguy.freeminecraftmodels.bukkit.Metrics; import com.magmaguy.magmacore.MagmaCore; import com.magmaguy.magmacore.command.CommandManager; import com.magmaguy.magmacore.util.Logger; @@ -44,6 +45,8 @@ public void onEnable() { if (Bukkit.getPluginManager().isPluginEnabled("FreeMinecraftModels")) Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); AutoHost.initialize(); + + Metrics metrics = new Metrics(this, 22867); } @Override From be0acb3b4561df86bae2b54c9d4f63906a955a59 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 3 Aug 2024 07:02:55 +0100 Subject: [PATCH 05/17] Note: Make sure to delete the mixer folder for this update. This should be the only time this is ever necessary. ResourcePackManager 1.0.1: - [New] Added Bstats - [New] Resource packs now get named after the plugin they come from to avoid namespace collisions - [New] Added BackpackPlus compatibility - [New] Added RealisticSurvival compatibility - [New] Added VaneCore compatibility - [New] Priority list in config.yml now lets admins define custom resource packs not associated to supported plugins - [New] Added new version notifier - [Fix] Mixer folder now correctly allows users to put custom resource packs in them for the resource pack generation - [Fix] Fixed ValhallaMMO compatibility --- .../ResourcePackManager.java | 3 + .../autohost/AutoHost.java | 2 +- .../config/DefaultConfig.java | 14 ++- .../resourcepackmanager/mixer/Mix.java | 83 +++++++++++--- .../thirdparty/BackpackPlus.java | 15 +++ .../thirdparty/RealisticSurvival.java | 13 +++ .../thirdparty/ThirdPartyResourcePack.java | 25 ++++- .../thirdparty/ValhallaMMO.java | 4 +- .../thirdparty/VaneCore.java | 13 +++ .../utils/VersionChecker.java | 106 ++++++++++++++++++ src/main/resources/plugin.yml | 5 +- 11 files changed, 260 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/utils/VersionChecker.java diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 6b1fe03..8ee6a1d 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -13,6 +13,7 @@ import com.magmaguy.resourcepackmanager.listeners.ResourcePackGeneratedEvent; import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; +import com.magmaguy.resourcepackmanager.utils.VersionChecker; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; @@ -44,9 +45,11 @@ public void onEnable() { commandManager.registerCommand(new DataComplianceRequestCommand()); if (Bukkit.getPluginManager().isPluginEnabled("FreeMinecraftModels")) Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); + Bukkit.getPluginManager().registerEvents(new VersionChecker.VersionCheckerEvents(), this); AutoHost.initialize(); Metrics metrics = new Metrics(this, 22867); + VersionChecker.checkPluginVersion(); } @Override diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index d7ea962..c97db1d 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -26,7 +26,7 @@ import java.util.UUID; public class AutoHost { -// private static final String finalURL = "http://localhost:3000/"; +// private static final String finalURL = "http://localhost:50000/"; private static final String finalURL = "http://magmaguy.com:50000/"; private static final UUID pluginRSPUUID = UUID.randomUUID(); private static BukkitTask keepAlive = null; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index 07574e9..d7e126c 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -29,7 +29,19 @@ public void initializeValues() { " packs will automatically resolve merge conflicts.", "The defaults use plugin names. If you manually added your own resource pack in the mixer folder to be merged in, add its exact filename, including .zip in the name"), fileConfiguration, "priorityOrder", - List.of("ResourcePackManager", "EliteMobs", "FreeMinecraftModels", "ModelEngine", "ItemsAdder", "Nova", "Oraxen", "BetterHUD", "ValhallaMMO", "MMOInventory")); + List.of( + "ResourcePackManager", + "EliteMobs", + "FreeMinecraftModels", + "ModelEngine", + "ItemsAdder", + "Nova", + "Oraxen", + "BetterHUD", + "ValhallaMMO", + "MMOInventory", + "vane-core", + "RealisticSurvival")); autoHost = ConfigurationEngine.setBoolean( List.of("Automatically host the resource pack on MagmaGuy's servers", diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 956692f..f0a61b1 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -5,6 +5,7 @@ import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; @@ -16,17 +17,21 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; - private static List thirdPartyResourcePacks; + private static final HashMap priorities = new HashMap<>(); + private static List resourcePacks; @Getter private static File finalResourcePack; @Getter private static String finalSHA1; @Getter private static byte[] finalSHA1Bytes; + private static File mixerFolder; private Mix() { } @@ -34,13 +39,13 @@ private Mix() { public static void initialize() { if (!initializeDefaultPluginFolders()) return; initializeThirdPartyResourcePacks(); - cloneToOutPutAndUnzip(); + cloneToOutputAndUnzip(); createOutputDefaultElements(); } private static boolean initializeDefaultPluginFolders() { try { - File mixerFolder = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "mixer"); + mixerFolder = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "mixer"); if (!mixerFolder.exists()) mixerFolder.mkdir(); File outputFolder = getOutputFolder(); @@ -82,27 +87,81 @@ private static void initializeThirdPartyResourcePacks() { ValhallaMMO valhallaMMO = new ValhallaMMO(); if (valhallaMMO.isEnabled()) tempList.add(valhallaMMO); - thirdPartyResourcePacks = new ArrayList<>(); + VaneCore vaneCore = new VaneCore(); + if (vaneCore.isEnabled()) + tempList.add(vaneCore); + BackpackPlus backpackPlus = new BackpackPlus(); + if (backpackPlus.isEnabled()) + tempList.add(backpackPlus); + RealisticSurvival realisticSurvival = new RealisticSurvival(); + if (realisticSurvival.isEnabled()) + tempList.add(backpackPlus); + resourcePacks = new ArrayList<>(); + List customFiles = new ArrayList<>(); + for (File file : mixerFolder.listFiles()) { + boolean isDefault = false; + for (File supportedRSP : resourcePacks) { + if (supportedRSP.equals(file)) { + isDefault = true; + break; + } + } + if (!isDefault) customFiles.add(file); + } + //Do resource packs with priority for (int i = 0; i < tempList.size(); i++) { + boolean foundFileAtPriority = false; for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { if (thirdPartyResourcePack.getPriority() == i) { - thirdPartyResourcePacks.add(thirdPartyResourcePack); + if (thirdPartyResourcePack.getMixerResourcePack() == null) continue; + resourcePacks.add(thirdPartyResourcePack.getMixerResourcePack()); tempList.remove(thirdPartyResourcePack); + foundFileAtPriority = true; + Logger.info("Added supported resource pack " + thirdPartyResourcePack.getFile().getName() + " at priority " + i); break; } } + if (!foundFileAtPriority) { + Iterator iterator = customFiles.iterator(); + while (iterator.hasNext()) { + File file = iterator.next(); + int priority = DefaultConfig.getPriorityOrder().indexOf(file.getName()); + if (priority == i) { + resourcePacks.add(file); + iterator.remove(); // Use iterator's remove method to avoid ConcurrentModificationException + Logger.info("Added custom resource pack " + file.getName() + " at priority " + i); + } + } + } + } + //Do resource packs with no priority + for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { + if (thirdPartyResourcePack.getMixerResourcePack() == null) continue; + resourcePacks.add(thirdPartyResourcePack.getMixerResourcePack()); + Logger.info("Added supported resource pack " + thirdPartyResourcePack.getMixerFilename() + " without a priority!"); + } + + for (File customFile : customFiles) { + Logger.info("Added custom resource pack " + customFile.getName() + " without a priority!"); + resourcePacks.add(customFile); } - thirdPartyResourcePacks.addAll(tempList); } - private static void cloneToOutPutAndUnzip() { - thirdPartyResourcePacks.forEach(thirdPartyResourcePack -> { + private static void cloneToOutputAndUnzip() { + resourcePacks.forEach(resourcePack -> { try { - File file = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "output" + File.separatorChar + thirdPartyResourcePack.getMixerResourcePack().getName().replace(".zip", "")); - ZipFile.unzip(thirdPartyResourcePack.getMixerResourcePack(), file); + if (resourcePack == null) { + Logger.warn("A resource pack was null by the time it was meant to be unzipped!"); + return; + } + File file = new File(ResourcePackManager.plugin.getDataFolder().getAbsolutePath() + File.separatorChar + "output" + File.separatorChar + resourcePack.getName().replace(".zip", "")); + ZipFile.unzip(resourcePack, file); stripDirectoryMetadata(file); } catch (Exception e) { - Logger.warn("Failed to extract file " + thirdPartyResourcePack.getMixerResourcePack().getAbsolutePath() + " ! The file might be encrypted."); + if (resourcePack == null) + Logger.warn("Failed to extract resource pack! A file might be encrypted."); + else + Logger.warn("Failed to extract resource pack " + resourcePack.getName() + " ! The file might be encrypted."); e.printStackTrace(); } }); @@ -167,14 +226,12 @@ private static void recursivelyDeleteDirectory(File directory) { Files.delete(directory.toPath()); } catch (Exception e) { Logger.warn("Failed to delete directory " + directory.getPath()); -// e.printStackTrace(); } } else { try { Files.delete(directory.toPath()); } catch (IOException e) { Logger.warn("Failed to delete file " + directory.getPath()); -// e.printStackTrace(); } } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java new file mode 100644 index 0000000..9ca5088 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +import java.io.File; + +public class BackpackPlus extends ThirdPartyResourcePack { + public BackpackPlus() { + super("BackpackPlus", + "https://download.mc-packs.net/pack/6998056b7754a0a2c71a61ba66f26908f6816194.zip", + false, + false, + true, + false, + ""); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java new file mode 100644 index 0000000..c69eb94 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +public class RealisticSurvival extends ThirdPartyResourcePack { + public RealisticSurvival() { + super("RealisticSurvival", + "https://www.dropbox.com/scl/fi/5ggc7t20bfxmrzsbb1kok/Realistic-Survival-RP-1.2.8-RELEASE.zip?rlkey=55llpn4zj146usfmm8okf1ier&dl=1", + false, + false, + true, + false, + ""); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index 6fb2855..f1555a9 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -20,6 +20,7 @@ import java.nio.file.StandardCopyOption; public class ThirdPartyResourcePack implements GeneratorInterface { + private final String pluginName; @Getter private File file = null; private String url; @@ -35,8 +36,9 @@ public class ThirdPartyResourcePack implements GeneratorInterface { @Getter private File mixerResourcePack = null; @Getter + private String mixerFilename; + @Getter private int priority = -1; - private final String pluginName; public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, boolean distributes, boolean zips, boolean local, String reloadCommand) { this.pluginName = pluginName; @@ -49,14 +51,22 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); else this.url = path; - if (!file.exists()) { + if (file != null && !file.exists()) { Logger.warn("Found " + pluginName + " but could not find resource pack at location " + file.getPath() + " ! ResourcePackManager will not be able to merge the resource pack from this plugin."); isEnabled = false; + return; } this.encrypts = encrypts; this.distributes = distributes; this.reloadCommand = reloadCommand; this.zips = zips; + mixerFilename = pluginName + "_" + (file.getName().endsWith(".zip") ? file.getName() : file.getName() + ".zip"); + if (!zips) { + ZipFile.zip(file, getTarget().toString()); + file = new File(getTarget().toUri()); + resourcePackUpdated = true; + mixerFilename = file.getName(); + } if (isEnabled && local) SHA1 = getSHA1(file); process(); if (DefaultConfig.getPriorityOrder().contains(pluginName)) @@ -75,10 +85,12 @@ public void process() { getTarget().toFile().delete(); } } - } else if (local && mixerCloneExists()) getTarget().toFile().delete(); + } +// } else if (local && mixerCloneExists()) getTarget().toFile().delete(); if (encrypts) decrypt(); if (distributes) unpublish(); - cloneResourcePackFile(); + if (zips) + cloneResourcePackFile(); } private String getSHA1(File file) { @@ -124,6 +136,7 @@ private void cloneLocalRSP() { } private void cloneRemoteRSP() { + Logger.info("Getting resource pack from remote URL! This is not ideal but not optional for some plugins. URL: " + url); try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost(url); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { @@ -136,6 +149,8 @@ private void cloneRemoteRSP() { zipFile.createNewFile(); try (FileOutputStream outStream = new FileOutputStream(zipFile)) { responseEntity.writeTo(outStream); + } catch (Exception e) { + Logger.warn("Failed to write resource pack from remote!"); } } } catch (Exception e) { @@ -156,6 +171,6 @@ private boolean mixerCloneExists() { } private Path getTarget() { - return Path.of(ResourcePackManager.plugin.getDataFolder().toString(), "mixer", file.getName().endsWith(".zip") ? file.getName() : file.getName() + ".zip"); + return Path.of(ResourcePackManager.plugin.getDataFolder().toString(), "mixer", mixerFilename); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java index d593d41..b7abf4d 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java @@ -5,10 +5,10 @@ public class ValhallaMMO extends ThirdPartyResourcePack { public ValhallaMMO() { super("ValhallaMMO", - "Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip", + "ValhallaMMO" + File.separatorChar + "resourcepack", + false, false, false, - true, true, ""); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java new file mode 100644 index 0000000..54b69bb --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.thirdparty; + +public class VaneCore extends ThirdPartyResourcePack { + public VaneCore() { + super("vane-core", + "vane-resource-pack.zip", + false, + true, + true, + true, + ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/utils/VersionChecker.java b/src/main/java/com/magmaguy/resourcepackmanager/utils/VersionChecker.java new file mode 100644 index 0000000..5341e96 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/utils/VersionChecker.java @@ -0,0 +1,106 @@ +package com.magmaguy.resourcepackmanager.utils; + +import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.resourcepackmanager.ResourcePackManager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Scanner; + +public class VersionChecker { + private static boolean pluginIsUpToDate = true; + + private VersionChecker() { + } + + public static void checkPluginVersion() { + new BukkitRunnable() { + @Override + public void run() { + String currentVersion = ResourcePackManager.plugin.getDescription().getVersion(); + boolean snapshot = false; + if (currentVersion.contains("SNAPSHOT")) { + snapshot = true; + currentVersion = currentVersion.split("-")[0]; + } + String publicVersion = ""; + + try { + Logger.info("Latest public release is " + VersionChecker.readStringFromURL("https://api.spigotmc.org/legacy/update.php?resource=118574")); + Logger.info("Your version is " + ResourcePackManager.plugin.getDescription().getVersion()); + publicVersion = VersionChecker.readStringFromURL("https://api.spigotmc.org/legacy/update.php?resource=118574"); + } catch (IOException e) { + Logger.warn("Couldn't check latest version"); + return; + } + + if (Double.parseDouble(currentVersion.split("\\.")[0]) < Double.parseDouble(publicVersion.split("\\.")[0])) { + outOfDateHandler(); + return; + } + + if (Double.parseDouble(currentVersion.split("\\.")[0]) == Double.parseDouble(publicVersion.split("\\.")[0])) { + + if (Double.parseDouble(currentVersion.split("\\.")[1]) < Double.parseDouble(publicVersion.split("\\.")[1])) { + outOfDateHandler(); + return; + } + + if (Double.parseDouble(currentVersion.split("\\.")[1]) == Double.parseDouble(publicVersion.split("\\.")[1])) { + if (Double.parseDouble(currentVersion.split("\\.")[2]) < Double.parseDouble(publicVersion.split("\\.")[2])) { + outOfDateHandler(); + return; + } + } + } + + if (!snapshot) + Logger.info("You are running the latest version!"); + else + Logger.info("You are running a snapshot version! You can check for updates in the #releases channel on the Nightbreak Discord!"); + + pluginIsUpToDate = true; + } + }.runTaskAsynchronously(ResourcePackManager.plugin); + } + + private static String readStringFromURL(String url) throws IOException { + + try (Scanner scanner = new Scanner(new URL(url).openStream(), + StandardCharsets.UTF_8)) { + scanner.useDelimiter("\\A"); + return scanner.hasNext() ? scanner.next() : ""; + } + + } + + private static void outOfDateHandler() { + Logger.warn("A newer version of this plugin is available for download!"); + pluginIsUpToDate = false; + } + + public static class VersionCheckerEvents implements Listener { + @EventHandler + public void onPlayerLogin(PlayerJoinEvent event) { + + if (!event.getPlayer().hasPermission("elitemobs.versionnotification")) return; + + new BukkitRunnable() { + @Override + public void run() { + if (!event.getPlayer().isOnline()) return; + if (!pluginIsUpToDate) + event.getPlayer().sendMessage(com.magmaguy.magmacore.util.ChatColorConverter.convert("&cYour version of ResourcePackManager is outdated." + + " &aYou can download the latest version from &3&n&ohttps://www.spigotmc.org/resources/resource-pack-manager.118574/")); + } + }.runTaskLater(ResourcePackManager.plugin, 20L * 3); + + } + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a4c9fbc..0db269f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.0.0 +version: 1.0.1 api-version: 1.14 softdepend: - EliteMobs @@ -9,6 +9,9 @@ softdepend: - Nova - Oraxen - ItemsAdder +- BackpackPlus +- vane-core +- RealisticSurvival commands: resourcepackmanager: From 7925925fc91ee1f29ea9833bc39c9b688762bd90 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 3 Aug 2024 16:44:50 +0100 Subject: [PATCH 06/17] ResourcePackManager 1.0.2: - [Fix] Fixed priority order not working correctly --- pom.xml | 2 +- .../autohost/AutoHost.java | 2 - .../resourcepackmanager/mixer/Mix.java | 148 +++++++++--------- .../thirdparty/ResourcePackManager.java | 2 +- .../thirdparty/ThirdPartyResourcePack.java | 7 +- src/main/resources/plugin.yml | 2 +- 6 files changed, 83 insertions(+), 80 deletions(-) diff --git a/pom.xml b/pom.xml index 6dbd6a2..5331a63 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.0.0 + 1.0.2 17 diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index c97db1d..1944d54 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -26,7 +26,6 @@ import java.util.UUID; public class AutoHost { -// private static final String finalURL = "http://localhost:50000/"; private static final String finalURL = "http://magmaguy.com:50000/"; private static final UUID pluginRSPUUID = UUID.randomUUID(); private static BukkitTask keepAlive = null; @@ -39,7 +38,6 @@ private AutoHost() { public static void sendResourcePack(Player player) { if (rspUUID == null) return; -// player.setResourcePack(pluginRSPUUID, finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); player.setResourcePack(finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index f0a61b1..ee4c240 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -16,15 +16,13 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; +import java.util.*; public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; private static final HashMap priorities = new HashMap<>(); private static List resourcePacks; + private static List orderedResourcePacks = new ArrayList<>(); @Getter private static File finalResourcePack; @Getter @@ -59,94 +57,99 @@ private static boolean initializeDefaultPluginFolders() { } private static void initializeThirdPartyResourcePacks() { - ArrayList tempList = new ArrayList<>(); - com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager resourcePackManager = new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(); - if (resourcePackManager.isEnabled()) - tempList.add(resourcePackManager); - EliteMobs eliteMobs = new EliteMobs(); - if (eliteMobs.isEnabled()) - tempList.add(eliteMobs); - FreeMinecraftModels freeMinecraftModels = new FreeMinecraftModels(); - if (freeMinecraftModels.isEnabled()) - tempList.add(freeMinecraftModels); - ModelEngine modelEngine = new ModelEngine(); - if (modelEngine.isEnabled()) - tempList.add(modelEngine); - ItemsAdder itemsAdder = new ItemsAdder(); - if (itemsAdder.isEnabled()) - tempList.add(itemsAdder); - Nova nova = new Nova(); - if (nova.isEnabled()) - tempList.add(nova); - Oraxen oraxen = new Oraxen(); - if (oraxen.isEnabled()) - tempList.add(oraxen); - BetterHUD betterHUD = new BetterHUD(); - if (betterHUD.isEnabled()) - tempList.add(betterHUD); - ValhallaMMO valhallaMMO = new ValhallaMMO(); - if (valhallaMMO.isEnabled()) - tempList.add(valhallaMMO); - VaneCore vaneCore = new VaneCore(); - if (vaneCore.isEnabled()) - tempList.add(vaneCore); - BackpackPlus backpackPlus = new BackpackPlus(); - if (backpackPlus.isEnabled()) - tempList.add(backpackPlus); - RealisticSurvival realisticSurvival = new RealisticSurvival(); - if (realisticSurvival.isEnabled()) - tempList.add(backpackPlus); + List tempList = new ArrayList<>(); + List resourcePackManagers = Arrays.asList( + new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(), + new EliteMobs(), + new FreeMinecraftModels(), + new ModelEngine(), + new ItemsAdder(), + new Nova(), + new Oraxen(), + new BetterHUD(), + new ValhallaMMO(), + new VaneCore(), + new BackpackPlus(), + new RealisticSurvival() + ); + + resourcePackManagers.stream() + .filter(ThirdPartyResourcePack::isEnabled) + .forEach(tempList::add); + resourcePacks = new ArrayList<>(); List customFiles = new ArrayList<>(); + List thirdPartyFiles = new ArrayList<>(); + + tempList.forEach(rsp -> { + if (rsp.getMixerResourcePack() != null) { + thirdPartyFiles.add(rsp.getMixerResourcePack()); + } + }); + for (File file : mixerFolder.listFiles()) { - boolean isDefault = false; - for (File supportedRSP : resourcePacks) { - if (supportedRSP.equals(file)) { - isDefault = true; + boolean isThirdParty = false; + for (File thirdPartyFile : thirdPartyFiles) { + if (file.getName().equals(thirdPartyFile.getName())) { + isThirdParty = true; break; } } - if (!isDefault) customFiles.add(file); + if (!isThirdParty) { + customFiles.add(file); + } } - //Do resource packs with priority - for (int i = 0; i < tempList.size(); i++) { + + for (int i = 0; i < DefaultConfig.getPriorityOrder().size(); i++) { boolean foundFileAtPriority = false; - for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { + Iterator iterator = tempList.iterator(); + + while (iterator.hasNext()) { + ThirdPartyResourcePack thirdPartyResourcePack = iterator.next(); if (thirdPartyResourcePack.getPriority() == i) { - if (thirdPartyResourcePack.getMixerResourcePack() == null) continue; - resourcePacks.add(thirdPartyResourcePack.getMixerResourcePack()); - tempList.remove(thirdPartyResourcePack); - foundFileAtPriority = true; - Logger.info("Added supported resource pack " + thirdPartyResourcePack.getFile().getName() + " at priority " + i); - break; + File resourcePackFile = thirdPartyResourcePack.getMixerResourcePack(); + if (resourcePackFile != null) { + resourcePacks.add(resourcePackFile); + orderedResourcePacks.add(resourcePackFile.getName().replace(".zip", "")); + iterator.remove(); + foundFileAtPriority = true; + break; + } } } + if (!foundFileAtPriority) { - Iterator iterator = customFiles.iterator(); - while (iterator.hasNext()) { - File file = iterator.next(); + Iterator fileIterator = customFiles.iterator(); + while (fileIterator.hasNext()) { + File file = fileIterator.next(); int priority = DefaultConfig.getPriorityOrder().indexOf(file.getName()); if (priority == i) { resourcePacks.add(file); - iterator.remove(); // Use iterator's remove method to avoid ConcurrentModificationException + orderedResourcePacks.add(file.getName().replace(".zip", "")); + fileIterator.remove(); Logger.info("Added custom resource pack " + file.getName() + " at priority " + i); } } } } - //Do resource packs with no priority - for (ThirdPartyResourcePack thirdPartyResourcePack : tempList) { - if (thirdPartyResourcePack.getMixerResourcePack() == null) continue; - resourcePacks.add(thirdPartyResourcePack.getMixerResourcePack()); - Logger.info("Added supported resource pack " + thirdPartyResourcePack.getMixerFilename() + " without a priority!"); - } - for (File customFile : customFiles) { - Logger.info("Added custom resource pack " + customFile.getName() + " without a priority!"); + tempList.stream() + .map(ThirdPartyResourcePack::getMixerResourcePack) + .filter(Objects::nonNull) + .forEach(resourcePack -> { + resourcePacks.add(resourcePack); + orderedResourcePacks.add(resourcePack.getName().replace(".zip", "")); + Logger.info("Added supported resource pack " + resourcePack.getName() + " without a priority!"); + }); + + customFiles.forEach(customFile -> { resourcePacks.add(customFile); - } + orderedResourcePacks.add(customFile.getName().replace(".zip", "")); + Logger.info("Added custom resource pack " + customFile.getName() + " without a priority!"); + }); } + private static void cloneToOutputAndUnzip() { resourcePacks.forEach(resourcePack -> { try { @@ -178,8 +181,13 @@ private static void createOutputDefaultElements() { throw new RuntimeException(e); } - for (File file : getOutputFolder().listFiles()) { - if (file.getName().equals(resourcePackName)) continue; + List orderedFiles = new ArrayList<>(); + for (String filename : orderedResourcePacks){ + orderedFiles.add(new File(getOutputFolder().getPath() + File.separatorChar + filename)); + } + + for (File file : orderedFiles) { + if (file.getName().equals(resourcePackName + ".zip")) continue; if (!file.isDirectory()) { if (file.getName().endsWith(".zip")) continue; Logger.warn("Somehow a non-folder file made its way to the output folder! This isn't good. File: " + file.getAbsolutePath()); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java index 59ad392..a15d979 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java @@ -10,6 +10,6 @@ public ResourcePackManager() { false, true, true, - "elitemobs reload"); + ""); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index f1555a9..f2c6d8b 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -20,6 +20,7 @@ import java.nio.file.StandardCopyOption; public class ThirdPartyResourcePack implements GeneratorInterface { + @Getter private final String pluginName; @Getter private File file = null; @@ -66,6 +67,7 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, file = new File(getTarget().toUri()); resourcePackUpdated = true; mixerFilename = file.getName(); + mixerResourcePack = file; } if (isEnabled && local) SHA1 = getSHA1(file); process(); @@ -86,7 +88,6 @@ public void process() { } } } -// } else if (local && mixerCloneExists()) getTarget().toFile().delete(); if (encrypts) decrypt(); if (distributes) unpublish(); if (zips) @@ -124,10 +125,6 @@ private void cloneLocalRSP() { if (zips) { Logger.info("Cloning resource pack from " + file.toPath()); mixerResourcePack = Files.copy(Path.of(file.getAbsolutePath()), Path.of(getTarget().toAbsolutePath().toString()), StandardCopyOption.REPLACE_EXISTING).toFile(); - } else { - if (mixerCloneExists()) getTarget().toFile().delete(); - Logger.info("Cloning resource pack from " + file.toPath()); - ZipFile.zip(file, getTarget().toString()); } } catch (Exception e) { Logger.warn("Failed to clone resource pack from " + file.getPath() + " to the mixer folder!"); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0db269f..440faed 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.0.1 +version: 1.0.2 api-version: 1.14 softdepend: - EliteMobs From 08f61c8f3174ad3e6b21de6f097138968c9776c4 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 7 Aug 2024 14:18:53 +0100 Subject: [PATCH 07/17] ResourcePackManager 1.1.0 - [New] Added a prototype API for plugins to register their plugins - [Fix] Fixed reloads breaking load order - [Fix] Fixed remote download not working for resource packs hosted in dropbox - [Tweak] Changed the way the plugin names resource packs in the mixer folder. Deleting the mixer folder for this update is very highly recommended. --- pom.xml | 8 +-- .../ResourcePackManager.java | 6 ++- .../api/ResourcePackManagerAPI.java | 41 ++++++++++++++ .../autohost/AutoHost.java | 2 +- .../config/DefaultConfig.java | 2 +- .../resourcepackmanager/mixer/Mix.java | 10 +++- .../thirdparty/BackpackPlus.java | 4 +- .../thirdparty/ThirdPartyResourcePack.java | 54 +++++++++++++------ src/main/resources/ReadMe.md | 2 +- src/main/resources/plugin.yml | 3 +- 10 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java diff --git a/pom.xml b/pom.xml index 5331a63..50a2c43 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.0.2 + 1.2.0 17 @@ -25,7 +25,7 @@ magmaguy-repo-releases MagmaGuy's Repository - http://magmaguy.com:50001/releases + https://repo.magmaguy.com/releases @@ -116,12 +116,12 @@ magmaguy-repo-snapshots - http://magmaguy.com:50001/snapshots + https://magmaguy.com/snapshots magmaguy-repo-snapshots MagmaGuy's Repository - http://magmaguy.com:50001/releases + https://repo.magmaguy.com/releases diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 8ee6a1d..93ff44a 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -31,7 +31,6 @@ public void onEnable() { " |_|_\\|___/_| |_| |_\\__,_|_||_\\__,_\\__, \\___|_| \n" + " |___/ "); Bukkit.getLogger().info("ResourcePackManager v." + this.getDescription().getVersion()); - MagmaCore.createInstance(this); plugin = this; new DefaultConfig(); @@ -52,6 +51,11 @@ public void onEnable() { VersionChecker.checkPluginVersion(); } + @Override + public void onLoad(){ + MagmaCore.createInstance(this); + } + @Override public void onDisable() { Logger.info("Disabling ResourcePackManager"); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java new file mode 100644 index 0000000..d1723bc --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java @@ -0,0 +1,41 @@ +package com.magmaguy.resourcepackmanager.api; + +import com.magmaguy.magmacore.command.CommandManager; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; +import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; + +import java.util.HashMap; + +public class ResourcePackManagerAPI { + public static HashMap thirdPartyResourcePackHashMap = new HashMap<>(); + + /** + * Please read and follow the parameters carefully. + * @param pluginName The name of the plugin as it appears in the plugin list. Case-sensitive. + * @param path The absolute path to the resource pack file (zipped or folder), or the URL to the resource pack. Zipped, local resource packs are strongly recommended. + * @param encrypts Whether the pack can be encrypted by the plugin. Currently does nothing. + * @param distributes Whether the plugin can distribute the pack. Currently does nothing. + * @param zips Whether the resource pack linked to is zipped. + * @param local Whether the resource pack is local or not, meaning whether it appears in the directory of the server or is provided as a download link. Local is strongly recommended. + * @param reloadCommand The reload command of the plugin adding a pack. Currently does nothing. + */ + public static void registerResourcePack(String pluginName, + String path, + boolean encrypts, + boolean distributes, + boolean zips, + boolean local, + String reloadCommand) { + thirdPartyResourcePackHashMap.put(pluginName, + new ThirdPartyResourcePack(pluginName, path, encrypts, distributes, zips, local, reloadCommand)); + } + + /** + * Reloads the plugin, thereby redoing everything necessary to merge and host the resource pack + */ + public static void reloadResourcePack(){ + ReloadCommand.reloadPlugin(Bukkit.getConsoleSender()); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index 1944d54..0751f81 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -72,7 +72,7 @@ public void run() { counter++; } } - }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 12 * 60 * 60 * 20L); + }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 6 * 60 * 60 * 20L); } }.runTaskAsynchronously(ResourcePackManager.plugin); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index d7e126c..b1ab705 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -34,8 +34,8 @@ public void initializeValues() { "EliteMobs", "FreeMinecraftModels", "ModelEngine", - "ItemsAdder", "Nova", + "ItemsAdder", "Oraxen", "BetterHUD", "ValhallaMMO", diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index ee4c240..92b21f1 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -5,6 +5,7 @@ import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.api.ResourcePackManagerAPI; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; @@ -20,9 +21,9 @@ public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; - private static final HashMap priorities = new HashMap<>(); + private static HashMap priorities; private static List resourcePacks; - private static List orderedResourcePacks = new ArrayList<>(); + private static List orderedResourcePacks; @Getter private static File finalResourcePack; @Getter @@ -57,6 +58,8 @@ private static boolean initializeDefaultPluginFolders() { } private static void initializeThirdPartyResourcePacks() { + orderedResourcePacks = new ArrayList<>(); + priorities = new HashMap(); List tempList = new ArrayList<>(); List resourcePackManagers = Arrays.asList( new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(), @@ -73,6 +76,9 @@ private static void initializeThirdPartyResourcePacks() { new RealisticSurvival() ); + //API resource packs + resourcePackManagers.addAll(ResourcePackManagerAPI.thirdPartyResourcePackHashMap.values()); + resourcePackManagers.stream() .filter(ThirdPartyResourcePack::isEnabled) .forEach(tempList::add); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java index 9ca5088..95f41e1 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java @@ -5,11 +5,11 @@ public class BackpackPlus extends ThirdPartyResourcePack { public BackpackPlus() { super("BackpackPlus", - "https://download.mc-packs.net/pack/6998056b7754a0a2c71a61ba66f26908f6816194.zip", + "BackpackPlus" +File.separatorChar+ "pack" +File.separatorChar + "resourcepack.zip", false, false, true, - false, + true, ""); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index f2c6d8b..20eb936 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -6,6 +6,7 @@ import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; +import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; @@ -13,8 +14,10 @@ import org.apache.hc.core5.http.HttpEntity; import org.bukkit.Bukkit; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -43,6 +46,7 @@ public class ThirdPartyResourcePack implements GeneratorInterface { public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, boolean distributes, boolean zips, boolean local, String reloadCommand) { this.pluginName = pluginName; + this.mixerFilename = pluginName + "_resource_pack.zip"; isEnabled = Bukkit.getPluginManager().isPluginEnabled(pluginName); if (isEnabled) Logger.info("Initializing " + pluginName + "'s resource pack"); @@ -61,12 +65,10 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, this.distributes = distributes; this.reloadCommand = reloadCommand; this.zips = zips; - mixerFilename = pluginName + "_" + (file.getName().endsWith(".zip") ? file.getName() : file.getName() + ".zip"); if (!zips) { ZipFile.zip(file, getTarget().toString()); file = new File(getTarget().toUri()); resourcePackUpdated = true; - mixerFilename = file.getName(); mixerResourcePack = file; } if (isEnabled && local) SHA1 = getSHA1(file); @@ -132,23 +134,43 @@ private void cloneLocalRSP() { } } - private void cloneRemoteRSP() { + public void cloneRemoteRSP() { Logger.info("Getting resource pack from remote URL! This is not ideal but not optional for some plugins. URL: " + url); try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost(url); - try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - HttpEntity responseEntity = response.getEntity(); - - if (responseEntity != null) { - // Save the response as a zip file - File zipFile = getTarget().toFile(); - if (zipFile.exists()) zipFile.delete(); - zipFile.createNewFile(); - try (FileOutputStream outStream = new FileOutputStream(zipFile)) { - responseEntity.writeTo(outStream); - } catch (Exception e) { - Logger.warn("Failed to write resource pack from remote!"); + HttpGet httpGet = new HttpGet(url); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + int statusCode = response.getCode(); + Logger.info("Response status code: " + statusCode); + + if (statusCode == 200) { + HttpEntity responseEntity = response.getEntity(); + if (responseEntity != null) { + // Save the response as a zip file + File zipFile = getTarget().toFile(); + if (zipFile.exists()) { + Logger.info("Target file exists, deleting it: " + zipFile.getAbsolutePath()); + zipFile.delete(); + } + zipFile.createNewFile(); + + try (InputStream inStream = new BufferedInputStream(responseEntity.getContent()); + FileOutputStream outStream = new FileOutputStream(zipFile)) { + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inStream.read(buffer)) != -1) { + outStream.write(buffer, 0, bytesRead); + } + + Logger.info("Successfully downloaded the resource pack to " + zipFile.getAbsolutePath()); + } catch (Exception e) { + Logger.warn("Failed to write resource pack from remote!"); + } + } else { + Logger.warn("Response entity is null"); } + } else { + Logger.warn("Unexpected response status: " + statusCode); } } catch (Exception e) { Logger.warn("Failed to communicate with remote server when downloading resource pack for plugin " + pluginName + "!"); diff --git a/src/main/resources/ReadMe.md b/src/main/resources/ReadMe.md index d24b2df..b7ca72c 100644 --- a/src/main/resources/ReadMe.md +++ b/src/main/resources/ReadMe.md @@ -27,7 +27,7 @@ To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\ - The zipped resource pack file is sent to the remote server, assigned the same UUID as the `.txt` file. This file can be obtained through `/resourcepackmanager data_compliance_request` and verified to be identical to the original in your output folder, as it is not modified by the Nightbreak servers. 5. **"Still Alive" Ping** - - ResourcePackManager sends a "still alive" ping every 12 hours, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. + - ResourcePackManager sends a "still alive" ping every 6 hours, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. - If no "still alive" ping is received for over 24 hours, all data associated with that UUID (the `.txt` file and the resource pack) is deleted from the Nightbreak servers. ### Data Policy diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 440faed..acd722c 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,8 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.0.2 +version: 1.2.0 api-version: 1.14 +author: MagmaGuy softdepend: - EliteMobs - FreeMinecraftModels From f224fc405a9cd7b586455ee0be48fc3d820d1bf9 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sun, 11 Aug 2024 23:22:35 +0100 Subject: [PATCH 08/17] ResourcePackManager 1.2.0 - [New] Added resource pack rerouting, which allows an optional setting in config.yml that will send the merged resource pack to a directory for use in other plugins --- pom.xml | 2 +- .../resourcepackmanager/autohost/AutoHost.java | 5 ++++- .../config/DefaultConfig.java | 13 ++++++++++++- .../magmaguy/resourcepackmanager/mixer/Mix.java | 16 ++++++++++++++++ .../playermanager/PlayerManager.java | 1 - src/main/resources/plugin.yml | 2 +- 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 50a2c43..e7614ec 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.2.0 + 1.2.1 17 diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index 0751f81..5cdeaaf 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -38,13 +38,14 @@ private AutoHost() { public static void sendResourcePack(Player player) { if (rspUUID == null) return; + Logger.info("Sending resource pack to " + player.getName()); player.setResourcePack(finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); - } public static void initialize() { if (!DefaultConfig.isAutoHost()) return; if (Mix.getFinalResourcePack() == null) return; + Logger.info("Starting autohost!"); firstUpload = true; new BukkitRunnable() { @Override @@ -106,6 +107,8 @@ public static void initializeLink() { } public static void uploadFile() { + Logger.info("Uploading resource!"); + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost uploadFile = new HttpPost(finalURL + "upload"); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index b1ab705..466c341 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -16,6 +16,9 @@ public class DefaultConfig extends ConfigurationFile { private static boolean forceResourcePack; @Getter private static String resourcePackPrompt; + @Getter + private static String resourcePackRerouting; + public DefaultConfig() { super("config.yml"); @@ -51,9 +54,17 @@ public void initializeValues() { forceResourcePack = ConfigurationEngine.setBoolean( List.of("Sets whether the resource pack use will be forced to clients"), fileConfiguration, "forceResourcePack", false); - resourcePackPrompt = ConfigurationEngine.setString( List.of("Sets whether the resource pack use will be forced to clients"), fileConfiguration, "resourcePackPrompt", "Use recommended resource pack?"); + resourcePackRerouting = ConfigurationEngine.setString( + List.of( + "OPTIONAL: Copy the merged directory to a custom directory location. Useful for unusual setups, like people trying to host with a different plugin.", + "If you are hosting with a different plugin make sure to disable Auto-hosting here!", + "This will use the plugin directory as the base directory.", + "As an example, if you wanted to target ResourcePackManager's output folder, you'd do:", + "ResourcePackManage/output", + "If you don't know what any of what is written here means, just don't touch this setting!"), + fileConfiguration, "resourcePackRerouting", ""); } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 92b21f1..f59ab6f 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -10,6 +10,7 @@ import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; +import org.bukkit.Bukkit; import java.io.File; import java.io.FileReader; @@ -207,6 +208,21 @@ private static void createOutputDefaultElements() { Logger.warn("Failed to zip merged resource pack!"); return; } + if (!DefaultConfig.getResourcePackRerouting().isEmpty() && !DefaultConfig.getResourcePackRerouting().isBlank()){ + try{ + File reroutFolder = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().getAbsolutePath() + File.separatorChar + DefaultConfig.getResourcePackRerouting()); + if (!reroutFolder.exists()) { + Logger.warn("Failed to reroute zipped file to " + reroutFolder.getAbsolutePath() + " because that folder does not exist!"); + } else if (!reroutFolder.isDirectory()){ + Logger.warn("Failed to reroute zipped file to " + reroutFolder.getAbsolutePath() + " because that is a file and not a folder!"); + } else if (!ZipFile.zip(getOutputResourcePackFolder(), reroutFolder.getPath() + ".zip")) { + Logger.warn("Failed to zip merged resource pack into reroute directory!"); + return; + } + } catch (Exception e){ + Logger.warn("Failed to reroute zipped file to " + DefaultConfig.getResourcePackRerouting()); + } + } for (File file : getOutputFolder().listFiles()) { if (file.getName().equals(resourcePackName + ".zip")) { finalResourcePack = file; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java index d8e67ae..3cfe328 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java @@ -10,7 +10,6 @@ public class PlayerManager implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - Logger.info("event"); AutoHost.sendResourcePack(event.getPlayer()); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index acd722c..a4168fb 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.2.0 +version: 1.2.1 api-version: 1.14 author: MagmaGuy softdepend: From ac12a7767ece5d2a855bfb4e0a75eb6bc933aab5 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 11 Nov 2024 01:19:16 +0000 Subject: [PATCH 09/17] Fix file handling inconsistencies in BetterHUD and Mix.java. Corrected the case sensitivity issue in the file path for BetterHUD. Renamed variable 'reroutFolder' to 'rerouteFolder' in Mix.java to ensure consistency in the rerouting mechanism. --- .../com/magmaguy/resourcepackmanager/mixer/Mix.java | 12 ++++++------ .../resourcepackmanager/thirdparty/BetterHUD.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index f59ab6f..0e5a13a 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -210,12 +210,12 @@ private static void createOutputDefaultElements() { } if (!DefaultConfig.getResourcePackRerouting().isEmpty() && !DefaultConfig.getResourcePackRerouting().isBlank()){ try{ - File reroutFolder = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().getAbsolutePath() + File.separatorChar + DefaultConfig.getResourcePackRerouting()); - if (!reroutFolder.exists()) { - Logger.warn("Failed to reroute zipped file to " + reroutFolder.getAbsolutePath() + " because that folder does not exist!"); - } else if (!reroutFolder.isDirectory()){ - Logger.warn("Failed to reroute zipped file to " + reroutFolder.getAbsolutePath() + " because that is a file and not a folder!"); - } else if (!ZipFile.zip(getOutputResourcePackFolder(), reroutFolder.getPath() + ".zip")) { + File rerouteFolder = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().getAbsolutePath() + File.separatorChar + DefaultConfig.getResourcePackRerouting()); + if (!rerouteFolder.exists()) { + Logger.warn("Failed to reroute zipped file to " + rerouteFolder.getAbsolutePath() + " because that folder does not exist!"); + } else if (!rerouteFolder.isDirectory()){ + Logger.warn("Failed to reroute zipped file to " + rerouteFolder.getAbsolutePath() + " because that is a file and not a folder!"); + } else if (!ZipFile.zip(getOutputResourcePackFolder(), rerouteFolder.getPath() + ".zip")) { Logger.warn("Failed to zip merged resource pack into reroute directory!"); return; } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java index 22602fe..b1b19d8 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java @@ -5,7 +5,7 @@ public class BetterHUD extends ThirdPartyResourcePack { public BetterHUD() { super("BetterHUD", - "BetterHUD" + File.separatorChar + "build.zip", + "BetterHud" + File.separatorChar + "build.zip", true, false, true, From a9b03cdbddecbf8f929461a05fa1c7d6d17193c3 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 14 Dec 2024 03:37:22 +0000 Subject: [PATCH 10/17] ResourcePackManager 1.2.2 - Fixed problem with rerouting files - Fixed compatibility for some plugins --- 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 e7614ec..776118c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.2.1 + 1.2.2 17 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a4168fb..1875fae 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.2.1 +version: 1.2.2 api-version: 1.14 author: MagmaGuy softdepend: From a139378517fd08228bdc2513ecddce165248baf8 Mon Sep 17 00:00:00 2001 From: MagmaGuy Date: Fri, 7 Feb 2025 20:10:43 +0000 Subject: [PATCH 11/17] ResourcePackManager 1.3.0 - [New] Improved commands - [New] Added /logify command to allow admins to easily upload their latest log to maclo.gs - [Fix] Fixed problem with rerouting files - [Fix] Fixed compatibility for some plugins --- pom.xml | 4 ++-- .../resourcepackmanager/ResourcePackManager.java | 9 +++++---- .../api/ResourcePackManagerAPI.java | 2 -- .../resourcepackmanager/autohost/AutoHost.java | 4 ++-- .../commands/DataComplianceRequestCommand.java | 2 -- .../resourcepackmanager/commands/ReloadCommand.java | 2 -- .../resourcepackmanager/config/BlueprintFolder.java | 2 +- .../listeners/ResourcePackGeneratedEvent.java | 4 ++-- .../com/magmaguy/resourcepackmanager/mixer/Mix.java | 3 +-- .../playermanager/PlayerManager.java | 1 - .../resourcepackmanager/thirdparty/EliteMobs.java | 2 -- .../thirdparty/GeneratorInterface.java | 2 -- .../resourcepackmanager/thirdparty/MMOInventory.java | 2 -- .../thirdparty/ThirdPartyResourcePack.java | 5 ++--- src/main/resources/plugin.yml | 10 ++++++++-- 15 files changed, 23 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 776118c..8ea2da1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.2.2 + 1.3.0 17 @@ -55,7 +55,7 @@ com.magmaguy MagmaCore - 1.7 + 1.8 compile diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 93ff44a..4da25dd 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -1,19 +1,19 @@ package com.magmaguy.resourcepackmanager; +import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; +import com.magmaguy.resourcepackmanager.utils.VersionChecker; import com.magmaguy.freeminecraftmodels.bukkit.Metrics; import com.magmaguy.magmacore.MagmaCore; import com.magmaguy.magmacore.command.CommandManager; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.autohost.AutoHost; -import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; -import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import com.magmaguy.resourcepackmanager.config.BlueprintFolder; import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; -import com.magmaguy.resourcepackmanager.listeners.ResourcePackGeneratedEvent; +import com.magmaguy.resourcepackmanager.Listeners.ResourcePackGeneratedEvent; import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; -import com.magmaguy.resourcepackmanager.utils.VersionChecker; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; @@ -31,6 +31,7 @@ public void onEnable() { " |_|_\\|___/_| |_| |_\\__,_|_||_\\__,_\\__, \\___|_| \n" + " |___/ "); Bukkit.getLogger().info("ResourcePackManager v." + this.getDescription().getVersion()); + MagmaCore.onEnable(); plugin = this; new DefaultConfig(); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java index d1723bc..84ed292 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java @@ -1,10 +1,8 @@ package com.magmaguy.resourcepackmanager.api; -import com.magmaguy.magmacore.command.CommandManager; import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; import java.util.HashMap; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index 5cdeaaf..1c5807f 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -1,10 +1,10 @@ package com.magmaguy.resourcepackmanager.autohost; -import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; +import com.magmaguy.resourcepackmanager.mixer.Mix; +import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; -import com.magmaguy.resourcepackmanager.mixer.Mix; import lombok.Getter; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java index b736562..6b4475c 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/DataComplianceRequestCommand.java @@ -5,8 +5,6 @@ import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.autohost.AutoHost; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; import java.util.List; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java index 51dfa2e..ad59f51 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java @@ -4,8 +4,6 @@ import com.magmaguy.magmacore.command.CommandData; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.ResourcePackManager; -import java.util.Collections; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import java.util.List; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java index 3a8c9f4..03966aa 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java @@ -1,8 +1,8 @@ package com.magmaguy.resourcepackmanager.config; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java index 07a5d6b..663c0e0 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java @@ -1,7 +1,7 @@ -package com.magmaguy.resourcepackmanager.listeners; +package com.magmaguy.resourcepackmanager.Listeners; -import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; import com.magmaguy.resourcepackmanager.commands.ReloadCommand; +import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 0e5a13a..a01f5c4 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -1,16 +1,15 @@ package com.magmaguy.resourcepackmanager.mixer; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.google.gson.*; import com.google.gson.stream.JsonReader; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.api.ResourcePackManagerAPI; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.thirdparty.*; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; -import org.bukkit.Bukkit; import java.io.File; import java.io.FileReader; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java index 3cfe328..d75e125 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/playermanager/PlayerManager.java @@ -1,6 +1,5 @@ package com.magmaguy.resourcepackmanager.playermanager; -import com.magmaguy.magmacore.util.Logger; import com.magmaguy.resourcepackmanager.autohost.AutoHost; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java index f4ca084..84903f7 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java @@ -1,7 +1,5 @@ package com.magmaguy.resourcepackmanager.thirdparty; -import lombok.Getter; - import java.io.File; public class EliteMobs extends ThirdPartyResourcePack { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java index 7f99791..a0c6e03 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java @@ -1,7 +1,5 @@ package com.magmaguy.resourcepackmanager.thirdparty; -import java.nio.file.Path; - public interface GeneratorInterface { public void decrypt(); public void unpublish(); diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java index 505dc3b..3323975 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java @@ -1,7 +1,5 @@ package com.magmaguy.resourcepackmanager.thirdparty; -import java.io.File; - public class MMOInventory extends ThirdPartyResourcePack { public MMOInventory() { super("MMOInventory", diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index 20eb936..16f514e 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -1,13 +1,12 @@ package com.magmaguy.resourcepackmanager.thirdparty; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; @@ -53,7 +52,7 @@ public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, else return; this.local = local; if (local) - this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); + this.file = new File(com.magmaguy.resourcepackmanager.ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); else this.url = path; if (file != null && !file.exists()) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1875fae..ebcd730 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.2.2 +version: 1.3.0 api-version: 1.14 author: MagmaGuy softdepend: @@ -18,4 +18,10 @@ commands: resourcepackmanager: aliases: - rspm - description: "Main command" \ No newline at end of file + description: "Main command" + logify: + description: Posts current latest.log in mclo.gs, to make reporting bugs easier for admins. +permissions: + logify.*: + description: Lets admins run the /logify command, which sends the current latest server log to mclo.gs. + default: op \ No newline at end of file From cb4c169473311ca774e70bddc5c2dbc21044f756 Mon Sep 17 00:00:00 2001 From: MagmaGuy Date: Fri, 20 Jun 2025 23:22:10 +0100 Subject: [PATCH 12/17] ResourcePackManager 1.4.1 - Fixed problem with rerouting files - Fixed compatibility for some plugins - [Fix] Fixed reported security issue with the logify command - [Fix] Fixed warnings related to the logify command --- pom.xml | 4 +- .../resourcepackmanager/JsonMerger.java | 4 - .../commands/ReloadCommand.java | 2 +- .../resourcepackmanager/mixer/Mix.java | 594 ++++++++++++++++-- src/main/resources/plugin.yml | 10 +- 5 files changed, 553 insertions(+), 61 deletions(-) delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/JsonMerger.java diff --git a/pom.xml b/pom.xml index 8ea2da1..21d1296 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.3.0 + 1.4.1 17 @@ -55,7 +55,7 @@ com.magmaguy MagmaCore - 1.8 + 1.15-SNAPSHOT compile diff --git a/src/main/java/com/magmaguy/resourcepackmanager/JsonMerger.java b/src/main/java/com/magmaguy/resourcepackmanager/JsonMerger.java deleted file mode 100644 index 0f9afb5..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/JsonMerger.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.magmaguy.resourcepackmanager; - -public class JsonMerger { -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java index ad59f51..5feb568 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/commands/ReloadCommand.java @@ -13,7 +13,7 @@ public ReloadCommand() { super(List.of("reload")); setDescription("Reloads the plugin"); setPermission("resourcepackmanager.*"); - setUsage("/fmm reload"); + setUsage("/rspm reload"); } public static void reloadPlugin(CommandSender sender) { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index a01f5c4..07eb578 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -11,13 +11,13 @@ import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.security.NoSuchAlgorithmException; import java.util.*; +import java.util.stream.Stream; public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; @@ -59,9 +59,10 @@ private static boolean initializeDefaultPluginFolders() { private static void initializeThirdPartyResourcePacks() { orderedResourcePacks = new ArrayList<>(); - priorities = new HashMap(); - List tempList = new ArrayList<>(); - List resourcePackManagers = Arrays.asList( + priorities = new HashMap<>(); + + // Use a mutable list so we can addAll() to it + List resourcePackManagers = new ArrayList<>(Arrays.asList( new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(), new EliteMobs(), new FreeMinecraftModels(), @@ -74,11 +75,13 @@ private static void initializeThirdPartyResourcePacks() { new VaneCore(), new BackpackPlus(), new RealisticSurvival() - ); + )); - //API resource packs + // Add any API-registered packs resourcePackManagers.addAll(ResourcePackManagerAPI.thirdPartyResourcePackHashMap.values()); + // Filter enabled packs into a working list + List tempList = new ArrayList<>(); resourcePackManagers.stream() .filter(ThirdPartyResourcePack::isEnabled) .forEach(tempList::add); @@ -87,67 +90,68 @@ private static void initializeThirdPartyResourcePacks() { List customFiles = new ArrayList<>(); List thirdPartyFiles = new ArrayList<>(); + // Collect actual pack files from each enabled pack tempList.forEach(rsp -> { - if (rsp.getMixerResourcePack() != null) { - thirdPartyFiles.add(rsp.getMixerResourcePack()); + File mixerPack = rsp.getMixerResourcePack(); + if (mixerPack != null) { + thirdPartyFiles.add(mixerPack); } }); + // Separate out truly custom files in the mixer folder for (File file : mixerFolder.listFiles()) { - boolean isThirdParty = false; - for (File thirdPartyFile : thirdPartyFiles) { - if (file.getName().equals(thirdPartyFile.getName())) { - isThirdParty = true; - break; - } - } + boolean isThirdParty = thirdPartyFiles.stream() + .anyMatch(tp -> tp.getName().equals(file.getName())); if (!isThirdParty) { customFiles.add(file); } } - for (int i = 0; i < DefaultConfig.getPriorityOrder().size(); i++) { - boolean foundFileAtPriority = false; - Iterator iterator = tempList.iterator(); - - while (iterator.hasNext()) { - ThirdPartyResourcePack thirdPartyResourcePack = iterator.next(); - if (thirdPartyResourcePack.getPriority() == i) { - File resourcePackFile = thirdPartyResourcePack.getMixerResourcePack(); - if (resourcePackFile != null) { - resourcePacks.add(resourcePackFile); - orderedResourcePacks.add(resourcePackFile.getName().replace(".zip", "")); - iterator.remove(); - foundFileAtPriority = true; + // Add in order of configured priority + List priorityOrder = DefaultConfig.getPriorityOrder(); + for (int i = 0; i < priorityOrder.size(); i++) { + boolean foundAtThisPriority = false; + + Iterator it = tempList.iterator(); + while (it.hasNext()) { + ThirdPartyResourcePack pack = it.next(); + if (pack.getPriority() == i) { + File f = pack.getMixerResourcePack(); + if (f != null) { + resourcePacks.add(f); + orderedResourcePacks.add(f.getName().replace(".zip", "")); + it.remove(); + foundAtThisPriority = true; break; } } } - if (!foundFileAtPriority) { - Iterator fileIterator = customFiles.iterator(); - while (fileIterator.hasNext()) { - File file = fileIterator.next(); - int priority = DefaultConfig.getPriorityOrder().indexOf(file.getName()); - if (priority == i) { - resourcePacks.add(file); - orderedResourcePacks.add(file.getName().replace(".zip", "")); - fileIterator.remove(); - Logger.info("Added custom resource pack " + file.getName() + " at priority " + i); + if (!foundAtThisPriority) { + Iterator fileIt = customFiles.iterator(); + while (fileIt.hasNext()) { + File custom = fileIt.next(); + int prio = priorityOrder.indexOf(custom.getName()); + if (prio == i) { + resourcePacks.add(custom); + orderedResourcePacks.add(custom.getName().replace(".zip", "")); + fileIt.remove(); } } } } + // Any remaining third-party packs without explicit priority tempList.stream() .map(ThirdPartyResourcePack::getMixerResourcePack) .filter(Objects::nonNull) - .forEach(resourcePack -> { - resourcePacks.add(resourcePack); - orderedResourcePacks.add(resourcePack.getName().replace(".zip", "")); - Logger.info("Added supported resource pack " + resourcePack.getName() + " without a priority!"); + .forEach(packFile -> { + resourcePacks.add(packFile); + orderedResourcePacks.add(packFile.getName().replace(".zip", "")); + Logger.info("Added supported resource pack " + packFile.getName() + " without a priority!"); }); + // Any leftover custom files without explicit priority customFiles.forEach(customFile -> { resourcePacks.add(customFile); orderedResourcePacks.add(customFile.getName().replace(".zip", "")); @@ -155,7 +159,6 @@ private static void initializeThirdPartyResourcePacks() { }); } - private static void cloneToOutputAndUnzip() { resourcePacks.forEach(resourcePack -> { try { @@ -207,6 +210,7 @@ private static void createOutputDefaultElements() { Logger.warn("Failed to zip merged resource pack!"); return; } + if (!DefaultConfig.getResourcePackRerouting().isEmpty() && !DefaultConfig.getResourcePackRerouting().isBlank()){ try{ File rerouteFolder = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().getAbsolutePath() + File.separatorChar + DefaultConfig.getResourcePackRerouting()); @@ -222,6 +226,7 @@ private static void createOutputDefaultElements() { Logger.warn("Failed to reroute zipped file to " + DefaultConfig.getResourcePackRerouting()); } } + for (File file : getOutputFolder().listFiles()) { if (file.getName().equals(resourcePackName + ".zip")) { finalResourcePack = file; @@ -236,6 +241,9 @@ private static void createOutputDefaultElements() { } recursivelyDeleteDirectory(file); } + +// // ADD THE BEDROCK CONVERSION CALL HERE - AFTER finalResourcePack IS SET: +// generateBedrockResourcePack(); } private static File getOutputFolder() { @@ -379,4 +387,498 @@ private static JsonArray mergeJsonArrays(JsonArray array1, JsonArray array2) { return mergedArray; } + +// +// @Getter +// private static File finalBedrockResourcePack; +// @Getter +// private static String finalBedrockSHA1; +// +// // Call this method in createOutputDefaultElements() after finalResourcePack is set +// private static void generateBedrockResourcePack() { +// if (finalResourcePack == null) { +// Logger.warn("Cannot generate Bedrock resource pack - Java resource pack was not created successfully!"); +// return; +// } +// +// Logger.info("Starting Bedrock resource pack generation..."); +// +// File bedrockOutputFolder = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + resourcePackName + "_Bedrock"); +// +// // Clean up any existing Bedrock folder +// if (bedrockOutputFolder.exists()) { +// recursivelyDeleteDirectory(bedrockOutputFolder); +// } +// +// try { +// bedrockOutputFolder.mkdirs(); +// +// // Extract the Java resource pack to process it +// File tempJavaFolder = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + "temp_java_extract"); +// if (tempJavaFolder.exists()) { +// recursivelyDeleteDirectory(tempJavaFolder); +// } +// tempJavaFolder.mkdirs(); +// +// ZipFile.unzip(finalResourcePack, tempJavaFolder); +// +// // Generate Bedrock pack contents +// generateBedrockManifest(bedrockOutputFolder); +// generateBehaviorPackManifest(bedrockOutputFolder); +// convertFreeMinecraftModelsAssets(tempJavaFolder, bedrockOutputFolder); +// +// // Create the Bedrock resource pack zip +// String bedrockPackName = resourcePackName + "_Bedrock.mcpack"; +// File bedrockZipFile = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + bedrockPackName); +// +// if (ZipFile.zip(bedrockOutputFolder, bedrockZipFile.getAbsolutePath())) { +// finalBedrockResourcePack = bedrockZipFile; +// try { +// finalBedrockSHA1 = SHA1Generator.sha1CodeString(finalBedrockResourcePack); +// Logger.info("Successfully generated Bedrock resource pack: " + bedrockPackName); +// } catch (Exception e) { +// Logger.warn("Failed to generate SHA1 for Bedrock resource pack!"); +// } +// } else { +// Logger.warn("Failed to zip Bedrock resource pack!"); +// } +// +// // Clean up temporary folders +// recursivelyDeleteDirectory(tempJavaFolder); +// recursivelyDeleteDirectory(bedrockOutputFolder); +// +// } catch (Exception e) { +// Logger.warn("Failed to generate Bedrock resource pack!"); +// e.printStackTrace(); +// } +// } +// +// private static void generateBedrockManifest(File bedrockOutputFolder) { +// try { +// JsonObject manifest = new JsonObject(); +// manifest.addProperty("format_version", 2); +// +// // Header +// JsonObject header = new JsonObject(); +// header.addProperty("name", "FreeMinecraftModels Bedrock"); +// header.addProperty("description", "Bedrock Edition conversion of FreeMinecraftModels resource pack"); +// header.addProperty("uuid", UUID.randomUUID().toString()); +// JsonArray headerVersion = new JsonArray(); +// headerVersion.add(1); headerVersion.add(0); headerVersion.add(0); +// header.add("version", headerVersion); +// JsonArray minEngineVersion = new JsonArray(); +// minEngineVersion.add(1); minEngineVersion.add(21); minEngineVersion.add(0); +// header.add("min_engine_version", minEngineVersion); +// manifest.add("header", header); +// +// // Modules +// JsonArray modules = new JsonArray(); +// JsonObject resourceModule = new JsonObject(); +// resourceModule.addProperty("type", "resources"); +// resourceModule.addProperty("uuid", UUID.randomUUID().toString()); +// JsonArray moduleVersion = new JsonArray(); +// moduleVersion.add(1); moduleVersion.add(0); moduleVersion.add(0); +// resourceModule.add("version", moduleVersion); +// modules.add(resourceModule); +// manifest.add("modules", modules); +// +// // Write manifest.json +// File manifestFile = new File(bedrockOutputFolder, "manifest.json"); +// try (FileWriter writer = new FileWriter(manifestFile)) { +// new Gson().toJson(manifest, writer); +// } +// +// } catch (Exception e) { +// Logger.warn("Failed to generate Bedrock manifest!"); +// e.printStackTrace(); +// } +// } +// +// private static void generateBehaviorPackManifest(File bedrockOutputFolder) { +// try { +// JsonObject manifest = new JsonObject(); +// manifest.addProperty("format_version", 2); +// +// // Header +// JsonObject header = new JsonObject(); +// header.addProperty("name", "FreeMinecraftModels Bedrock Behavior"); +// header.addProperty("description", "Behavior pack for FreeMinecraftModels custom bone items"); +// header.addProperty("uuid", UUID.randomUUID().toString()); +// JsonArray headerVersion = new JsonArray(); +// headerVersion.add(1); headerVersion.add(0); headerVersion.add(0); +// header.add("version", headerVersion); +// JsonArray minEngineVersion = new JsonArray(); +// minEngineVersion.add(1); minEngineVersion.add(21); minEngineVersion.add(0); +// header.add("min_engine_version", minEngineVersion); +// manifest.add("header", header); +// +// // Modules +// JsonArray modules = new JsonArray(); +// JsonObject behaviorModule = new JsonObject(); +// behaviorModule.addProperty("type", "data"); +// behaviorModule.addProperty("uuid", UUID.randomUUID().toString()); +// JsonArray moduleVersion = new JsonArray(); +// moduleVersion.add(1); moduleVersion.add(0); moduleVersion.add(0); +// behaviorModule.add("version", moduleVersion); +// modules.add(behaviorModule); +// manifest.add("modules", modules); +// +// // Write BP manifest.json +// File bpFolder = new File(bedrockOutputFolder, "BP"); +// bpFolder.mkdirs(); +// File manifestFile = new File(bpFolder, "manifest.json"); +// try (FileWriter writer = new FileWriter(manifestFile)) { +// new Gson().toJson(manifest, writer); +// } +// +// } catch (Exception e) { +// Logger.warn("Failed to generate Behavior Pack manifest!"); +// e.printStackTrace(); +// } +// } +// +// private static void convertFreeMinecraftModelsAssets(File javaFolder, File bedrockFolder) { +// File freeMinecraftModelsAssets = new File(javaFolder, "assets" + File.separator + "freeminecraftmodels"); +// if (!freeMinecraftModelsAssets.exists()) { +// Logger.info("No FreeMinecraftModels assets found to convert"); +// return; +// } +// +// Logger.info("Converting FreeMinecraftModels assets to Bedrock format..."); +// +// try { +// // Create Bedrock directory structure +// File attachablesDir = new File(bedrockFolder, "attachables"); +// File modelsDir = new File(bedrockFolder, "models" + File.separator + "entity"); +// File texturesDir = new File(bedrockFolder, "textures" + File.separator + "entity"); +// +// attachablesDir.mkdirs(); +// modelsDir.mkdirs(); +// texturesDir.mkdirs(); +// +// // Copy textures first +// File javaTexturesDir = new File(freeMinecraftModelsAssets, "textures" + File.separator + "entity"); +// if (javaTexturesDir.exists()) { +// copyTexturesRecursively(javaTexturesDir, texturesDir); +// } +// +// // Convert Java models to Bedrock - each bone becomes separate item +// File javaModelsDir = new File(freeMinecraftModelsAssets, "models"); +// if (javaModelsDir.exists()) { +// convertJavaModelsToBedrock(javaModelsDir, attachablesDir, modelsDir, bedrockFolder); +// } +// +// } catch (Exception e) { +// Logger.warn("Failed to convert FreeMinecraftModels assets!"); +// e.printStackTrace(); +// } +// } +// +// private static void copyTexturesRecursively(File sourceDir, File targetDir) { +// if (!sourceDir.exists() || !sourceDir.isDirectory()) return; +// +// try { +// for (File file : sourceDir.listFiles()) { +// if (file.isDirectory()) { +// File newTargetDir = new File(targetDir, file.getName()); +// newTargetDir.mkdirs(); +// copyTexturesRecursively(file, newTargetDir); +// } else if (file.getName().endsWith(".png")) { +// File targetFile = new File(targetDir, file.getName()); +// Files.copy(file.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); +// } +// } +// } catch (Exception e) { +// Logger.warn("Failed to copy textures from " + sourceDir.getName()); +// e.printStackTrace(); +// } +// } +// +// private static void convertJavaModelsToBedrock(File javaModelsDir, File attachablesDir, File modelsDir, File bedrockFolder) { +// // Look for model folders (each model has its own folder with bone JSON files) +// for (File modelFolder : javaModelsDir.listFiles()) { +// if (!modelFolder.isDirectory()) continue; +// +// String modelName = modelFolder.getName(); +// +// // Skip equipment folder - that's for 1.21.4+ format +// if (modelName.equals("equipment")) continue; +// +// Logger.info("Converting model: " + modelName); +// +// try { +// // Process each bone file individually - each becomes a separate item +// convertModelBonesToBedrock(modelFolder, modelName, attachablesDir, modelsDir, bedrockFolder); +// +// } catch (Exception e) { +// Logger.warn("Failed to convert model: " + modelName); +// e.printStackTrace(); +// } +// } +// } +// +// private static void convertModelBonesToBedrock(File modelFolder, String modelName, File attachablesDir, File modelsDir, File bedrockFolder) { +// // Process each bone file as a separate item/geometry +// List boneFiles = new ArrayList<>(); +// collectBoneFiles(modelFolder, boneFiles); +// +// for (File boneFile : boneFiles) { +// String boneName = boneFile.getName().replace(".json", ""); +// +// // Skip the root bone +// if (boneName.equals("freeminecraftmodels_autogenerated_root")) continue; +// +// Logger.info("Converting bone: " + boneName + " from model: " + modelName); +// +// try { +// // Create unique identifiers for this bone +// String boneId = modelName + "_" + boneName; +// String itemId = "fmm_bone_" + boneId; +// +// // Convert bone to Bedrock geometry +// convertSingleBoneToBedrock(boneFile, boneName, modelName, modelsDir); +// +// // Create attachable for this bone +// generateBoneAttachable(itemId, boneName, modelName, attachablesDir); +// +// // Create behavior pack item for this bone +// generateBoneItem(itemId, boneName, modelName, bedrockFolder); +// +// } catch (Exception e) { +// Logger.warn("Failed to convert bone: " + boneName + " from model: " + modelName); +// e.printStackTrace(); +// } +// } +// } +// +// private static void collectBoneFiles(File folder, List boneFiles) { +// for (File file : folder.listFiles()) { +// if (file.isDirectory()) { +// collectBoneFiles(file, boneFiles); +// } else if (file.getName().endsWith(".json")) { +// boneFiles.add(file); +// } +// } +// } +// +// private static void convertSingleBoneToBedrock(File boneFile, String boneName, String modelName, File modelsDir) { +// try { +// // Read Java bone model +// JsonObject javaModel = JsonParser.parseReader(new FileReader(boneFile)).getAsJsonObject(); +// +// // Create Bedrock geometry +// JsonObject geometry = new JsonObject(); +// geometry.addProperty("format_version", "1.21.0"); +// +// JsonArray geometryArray = new JsonArray(); +// JsonObject geometryDef = new JsonObject(); +// +// JsonObject description = new JsonObject(); +// description.addProperty("identifier", "geometry.fmm_bone." + modelName + "_" + boneName); +// description.addProperty("texture_width", 64); +// description.addProperty("texture_height", 64); +// geometryDef.add("description", description); +// +// JsonArray bones = new JsonArray(); +// +// // Create root bone +// JsonObject rootBone = new JsonObject(); +// rootBone.addProperty("name", "root"); +// JsonArray pivot = new JsonArray(); +// pivot.add(0); pivot.add(0); pivot.add(0); +// rootBone.add("pivot", pivot); +// +// // Convert elements (cubes) to Bedrock format +// if (javaModel.has("elements")) { +// JsonArray elements = javaModel.getAsJsonArray("elements"); +// JsonArray cubes = new JsonArray(); +// +// for (int i = 0; i < elements.size(); i++) { +// JsonObject element = elements.get(i).getAsJsonObject(); +// JsonObject bedrockCube = convertJavaCubeToBedrock(element); +// if (bedrockCube != null) { +// cubes.add(bedrockCube); +// } +// } +// +// if (cubes.size() > 0) { +// rootBone.add("cubes", cubes); +// } +// } +// +// bones.add(rootBone); +// geometryDef.add("bones", bones); +// geometryArray.add(geometryDef); +// geometry.add("minecraft:geometry", geometryArray); +// +// // Write geometry file +// File geoFile = new File(modelsDir, "fmm_bone_" + modelName + "_" + boneName + ".geo.json"); +// try (FileWriter writer = new FileWriter(geoFile)) { +// new Gson().toJson(geometry, writer); +// } +// +// } catch (Exception e) { +// Logger.warn("Failed to convert bone: " + boneName); +// e.printStackTrace(); +// } +// } +// +// private static JsonObject convertJavaCubeToBedrock(JsonObject javaCube) { +// try { +// JsonObject bedrockCube = new JsonObject(); +// +// // Convert origin (from in Java) +// if (javaCube.has("from")) { +// JsonArray from = javaCube.getAsJsonArray("from"); +// JsonArray origin = new JsonArray(); +// origin.add(from.get(0)); +// origin.add(from.get(1)); +// origin.add(from.get(2)); +// bedrockCube.add("origin", origin); +// } +// +// // Convert size (to - from in Java) +// if (javaCube.has("from") && javaCube.has("to")) { +// JsonArray from = javaCube.getAsJsonArray("from"); +// JsonArray to = javaCube.getAsJsonArray("to"); +// JsonArray size = new JsonArray(); +// size.add(to.get(0).getAsDouble() - from.get(0).getAsDouble()); +// size.add(to.get(1).getAsDouble() - from.get(1).getAsDouble()); +// size.add(to.get(2).getAsDouble() - from.get(2).getAsDouble()); +// bedrockCube.add("size", size); +// } +// +// // Convert UV mapping - extract from faces +// if (javaCube.has("faces")) { +// JsonObject faces = javaCube.getAsJsonObject("faces"); +// // Use north face UV as default, or first available face +// JsonObject northFace = null; +// +// if (faces.has("north")) northFace = faces.getAsJsonObject("north"); +// else if (faces.has("south")) northFace = faces.getAsJsonObject("south"); +// else if (faces.has("east")) northFace = faces.getAsJsonObject("east"); +// else if (faces.has("west")) northFace = faces.getAsJsonObject("west"); +// else if (faces.has("up")) northFace = faces.getAsJsonObject("up"); +// else if (faces.has("down")) northFace = faces.getAsJsonObject("down"); +// +// if (northFace != null && northFace.has("uv")) { +// JsonArray javaUV = northFace.getAsJsonArray("uv"); +// JsonArray bedrockUV = new JsonArray(); +// bedrockUV.add(javaUV.get(0)); +// bedrockUV.add(javaUV.get(1)); +// bedrockCube.add("uv", bedrockUV); +// } else { +// // Default UV +// JsonArray uv = new JsonArray(); +// uv.add(0); uv.add(0); +// bedrockCube.add("uv", uv); +// } +// } +// +// return bedrockCube; +// +// } catch (Exception e) { +// Logger.warn("Failed to convert Java cube to Bedrock format"); +// return null; +// } +// } +// +// private static void generateBoneAttachable(String itemId, String boneName, String modelName, File attachablesDir) { +// try { +// JsonObject attachable = new JsonObject(); +// attachable.addProperty("format_version", "1.10.0"); +// +// JsonObject attachableData = new JsonObject(); +// JsonObject description = new JsonObject(); +// description.addProperty("identifier", "fmm:" + itemId); +// +// JsonObject materials = new JsonObject(); +// materials.addProperty("default", "entity_alphatest"); +// materials.addProperty("enchanted", "entity_alphatest_glint"); +// description.add("materials", materials); +// +// JsonObject textures = new JsonObject(); +// // Try to find appropriate texture path +// String texturePath = "textures/entity/" + modelName + "/texture"; +// textures.addProperty("default", texturePath); +// description.add("textures", textures); +// +// JsonObject geometry = new JsonObject(); +// geometry.addProperty("default", "geometry.fmm_bone." + modelName + "_" + boneName); +// description.add("geometry", geometry); +// +// // Configure for handheld/inventory item display +// JsonArray scripts = new JsonArray(); +// JsonObject animateScript = new JsonObject(); +// animateScript.addProperty("animate", "third_person_main_hand"); +// scripts.add(animateScript); +// description.add("scripts", scripts); +// +// attachableData.add("description", description); +// attachable.add("minecraft:attachable", attachableData); +// +// File attachableFile = new File(attachablesDir, itemId + ".json"); +// try (FileWriter writer = new FileWriter(attachableFile)) { +// new Gson().toJson(attachable, writer); +// } +// +// Logger.info("Created attachable: fmm:" + itemId); +// +// } catch (Exception e) { +// Logger.warn("Failed to generate attachable for " + itemId); +// e.printStackTrace(); +// } +// } +// +// private static void generateBoneItem(String itemId, String boneName, String modelName, File bedrockFolder) { +// try { +// // Create BP items folder +// File bpItemsDir = new File(bedrockFolder, "BP" + File.separator + "items"); +// bpItemsDir.mkdirs(); +// +// JsonObject item = new JsonObject(); +// item.addProperty("format_version", "1.21.0"); +// +// JsonObject minecraftItem = new JsonObject(); +// JsonObject description = new JsonObject(); +// description.addProperty("identifier", "fmm:" + itemId); +// description.addProperty("category", "Items"); +// minecraftItem.add("description", description); +// +// JsonObject components = new JsonObject(); +// +// // Set max stack size +// components.addProperty("minecraft:max_stack_size", 64); +// +// // Set icon - use leather horse armor for now +// components.addProperty("minecraft:icon", "leather_horse_armor"); +// +// // Set display name +// JsonObject displayName = new JsonObject(); +// displayName.addProperty("value", modelName + " " + boneName.replace("_", " ")); +// components.add("minecraft:display_name", displayName); +// +// // Set attachable for handheld items +// JsonObject attachable = new JsonObject(); +// attachable.addProperty("slot", "mainhand"); +// attachable.addProperty("attachable", "fmm:" + itemId); +// components.add("minecraft:attachable", attachable); +// +// minecraftItem.add("components", components); +// item.add("minecraft:item", minecraftItem); +// +// File itemFile = new File(bpItemsDir, itemId + ".json"); +// try (FileWriter writer = new FileWriter(itemFile)) { +// new Gson().toJson(item, writer); +// } +// +// Logger.info("Created custom bone item: fmm:" + itemId); +// +// } catch (Exception e) { +// Logger.warn("Failed to generate behavior pack item for " + itemId); +// e.printStackTrace(); +// } +// } + } + diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ebcd730..2b025a9 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.3.0 +version: 1.4.1 api-version: 1.14 author: MagmaGuy softdepend: @@ -18,10 +18,4 @@ commands: resourcepackmanager: aliases: - rspm - description: "Main command" - logify: - description: Posts current latest.log in mclo.gs, to make reporting bugs easier for admins. -permissions: - logify.*: - description: Lets admins run the /logify command, which sends the current latest server log to mclo.gs. - default: op \ No newline at end of file + description: "Main command" \ No newline at end of file From d29b88545250a1d6bffd9772b3d23cc38a9f6e8e Mon Sep 17 00:00:00 2001 From: MagmaGuy Date: Sat, 26 Jul 2025 15:56:07 +0100 Subject: [PATCH 13/17] Resource Pack Manager 1.5.0: - [New] Full remake of core elements of the plugin! - [New] It is now possible to customize plugins that are supported, and even add support for new plugins via configuration files - [Fix] Fixed a lot of issues that would cause resource packs to fail to upload, fail to download or fail to load. --- pom.xml | 4 +- .../ResourcePackManager.java | 18 +- .../api/ResourcePackManagerAPI.java | 67 ++- .../autohost/AutoHost.java | 219 ++++++- .../config/BlueprintFolder.java | 2 +- .../config/DataConfig.java | 69 ++- .../CompatiblePluginConfig.java | 19 + .../CompatiblePluginConfigFields.java | 57 ++ .../premade/BackpackPlus.java | 13 + .../compatibleplugins/premade/BetterHUD.java | 15 + .../compatibleplugins/premade/EliteMobs.java | 14 + .../premade/FreeMinecraftModels.java | 14 + .../compatibleplugins/premade/ItemsAdder.java | 15 + .../premade/MMOInventory.java | 11 + .../premade/ModelEngine.java | 14 + .../compatibleplugins/premade/Nova.java | 13 + .../compatibleplugins/premade/Oraxen.java | 13 + .../premade/RealisticSurvival.java | 11 + .../premade/ResourcePackManager.java | 14 + .../premade/ValhallaMMO.java | 14 + .../compatibleplugins/premade/VaneCore.java | 12 + .../datacompliance/DataCompliance.java | 4 - .../listeners/ResourcePackGeneratedEvent.java | 4 +- .../resourcepackmanager/mixer/Mix.java | 538 +----------------- .../thirdparty/BackpackPlus.java | 15 - .../thirdparty/BetterHUD.java | 15 - .../thirdparty/EliteMobs.java | 15 - .../thirdparty/FreeMinecraftModels.java | 15 - .../thirdparty/GeneratorInterface.java | 11 +- .../thirdparty/ItemsAdder.java | 15 - .../thirdparty/MMOInventory.java | 13 - .../thirdparty/ModelEngine.java | 15 - .../resourcepackmanager/thirdparty/Nova.java | 15 - .../thirdparty/Oraxen.java | 15 - .../thirdparty/RealisticSurvival.java | 13 - .../thirdparty/ResourcePackManager.java | 15 - .../thirdparty/ThirdPartyResourcePack.java | 119 ++-- .../thirdparty/ValhallaMMO.java | 15 - .../thirdparty/VaneCore.java | 13 - src/main/resources/ReadMe.md | 55 +- src/main/resources/plugin.yml | 20 +- 41 files changed, 735 insertions(+), 833 deletions(-) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfig.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfigFields.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BackpackPlus.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BetterHUD.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/EliteMobs.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/FreeMinecraftModels.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ItemsAdder.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/MMOInventory.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ModelEngine.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nova.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Oraxen.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/RealisticSurvival.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ResourcePackManager.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ValhallaMMO.java create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/VaneCore.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java diff --git a/pom.xml b/pom.xml index 21d1296..fb306aa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.4.1 + 1.5.0 17 @@ -55,7 +55,7 @@ com.magmaguy MagmaCore - 1.15-SNAPSHOT + 1.18-SNAPSHOT compile diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index 4da25dd..bb174db 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -1,19 +1,21 @@ package com.magmaguy.resourcepackmanager; -import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; -import com.magmaguy.resourcepackmanager.commands.ReloadCommand; -import com.magmaguy.resourcepackmanager.utils.VersionChecker; import com.magmaguy.freeminecraftmodels.bukkit.Metrics; import com.magmaguy.magmacore.MagmaCore; import com.magmaguy.magmacore.command.CommandManager; import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.resourcepackmanager.listeners.ResourcePackGeneratedEvent; import com.magmaguy.resourcepackmanager.autohost.AutoHost; +import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import com.magmaguy.resourcepackmanager.config.BlueprintFolder; import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; -import com.magmaguy.resourcepackmanager.Listeners.ResourcePackGeneratedEvent; +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfig; import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; +import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; +import com.magmaguy.resourcepackmanager.utils.VersionChecker; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; @@ -34,8 +36,9 @@ public void onEnable() { MagmaCore.onEnable(); plugin = this; - new DefaultConfig(); new DataConfig(); + new DefaultConfig(); + new CompatiblePluginConfig(); BlueprintFolder.initialize(); Mix.initialize(); if (DefaultConfig.isAutoHost()) @@ -49,17 +52,18 @@ public void onEnable() { AutoHost.initialize(); Metrics metrics = new Metrics(this, 22867); - VersionChecker.checkPluginVersion(); + MagmaCore.checkVersionUpdate("118574", "https://www.spigotmc.org/resources/resource-pack-manager.118574/"); } @Override - public void onLoad(){ + public void onLoad() { MagmaCore.createInstance(this); } @Override public void onDisable() { Logger.info("Disabling ResourcePackManager"); + ThirdPartyResourcePack.shutdown(); HandlerList.unregisterAll(this); AutoHost.shutdown(); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java index 84ed292..736a17a 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/api/ResourcePackManagerAPI.java @@ -10,30 +10,73 @@ public class ResourcePackManagerAPI { public static HashMap thirdPartyResourcePackHashMap = new HashMap<>(); /** - * Please read and follow the parameters carefully. - * @param pluginName The name of the plugin as it appears in the plugin list. Case-sensitive. - * @param path The absolute path to the resource pack file (zipped or folder), or the URL to the resource pack. Zipped, local resource packs are strongly recommended. - * @param encrypts Whether the pack can be encrypted by the plugin. Currently does nothing. - * @param distributes Whether the plugin can distribute the pack. Currently does nothing. - * @param zips Whether the resource pack linked to is zipped. - * @param local Whether the resource pack is local or not, meaning whether it appears in the directory of the server or is provided as a download link. Local is strongly recommended. + * Registers a resource pack with the ResourcePackManager. + * Either localPath or url must be provided (non-null), but not both. + * + * @param pluginName The name of the plugin as it appears in the plugin list. Case-sensitive. + * @param localPath The relative path to the resource pack file (zipped or folder) from the plugins directory, or null if using URL. + * @param url The URL to download the resource pack from, or null if using local path. + * @param encrypts Whether the pack can be encrypted by the plugin. Currently does nothing. + * @param distributes Whether the plugin can distribute the pack. Currently does nothing. + * @param zips Whether the resource pack is already zipped. If false, ResourcePackManager will zip it. * @param reloadCommand The reload command of the plugin adding a pack. Currently does nothing. */ public static void registerResourcePack(String pluginName, - String path, + String localPath, + String url, boolean encrypts, boolean distributes, boolean zips, - boolean local, String reloadCommand) { thirdPartyResourcePackHashMap.put(pluginName, - new ThirdPartyResourcePack(pluginName, path, encrypts, distributes, zips, local, reloadCommand)); + new ThirdPartyResourcePack(pluginName, localPath, url, encrypts, distributes, zips, reloadCommand)); + } + + /** + * Registers a local resource pack with the ResourcePackManager. + * + * @param pluginName The name of the plugin as it appears in the plugin list. Case-sensitive. + * @param localPath The relative path to the resource pack file (zipped or folder) from the plugins directory. + * @param encrypts Whether the pack can be encrypted by the plugin. Currently does nothing. + * @param distributes Whether the plugin can distribute the pack. Currently does nothing. + * @param zips Whether the resource pack is already zipped. If false, ResourcePackManager will zip it. + * @param reloadCommand The reload command of the plugin adding a pack. Currently does nothing. + */ + public static void registerLocalResourcePack(String pluginName, + String localPath, + boolean encrypts, + boolean distributes, + boolean zips, + String reloadCommand) { + thirdPartyResourcePackHashMap.put(pluginName, + new ThirdPartyResourcePack(pluginName, localPath, null, encrypts, distributes, zips, reloadCommand)); + } + + /** + * Registers a remote resource pack with the ResourcePackManager. + * The resource pack will be downloaded from the provided URL. + * + * @param pluginName The name of the plugin as it appears in the plugin list. Case-sensitive. + * @param url The URL to download the resource pack from. + * @param encrypts Whether the pack can be encrypted by the plugin. Currently does nothing. + * @param distributes Whether the plugin can distribute the pack. Currently does nothing. + * @param zips Whether the resource pack from the URL is already zipped. If false, ResourcePackManager will zip it. + * @param reloadCommand The reload command of the plugin adding a pack. Currently does nothing. + */ + public static void registerRemoteResourcePack(String pluginName, + String url, + boolean encrypts, + boolean distributes, + boolean zips, + String reloadCommand) { + thirdPartyResourcePackHashMap.put(pluginName, + new ThirdPartyResourcePack(pluginName, null, url, encrypts, distributes, zips, reloadCommand)); } /** * Reloads the plugin, thereby redoing everything necessary to merge and host the resource pack */ - public static void reloadResourcePack(){ + public static void reloadResourcePack() { ReloadCommand.reloadPlugin(Bukkit.getConsoleSender()); } -} +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index 1c5807f..b50be98 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -1,10 +1,12 @@ package com.magmaguy.resourcepackmanager.autohost; -import com.magmaguy.resourcepackmanager.ResourcePackManager; -import com.magmaguy.resourcepackmanager.mixer.Mix; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import com.magmaguy.magmacore.util.Logger; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; +import com.magmaguy.resourcepackmanager.mixer.Mix; import lombok.Getter; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; @@ -23,11 +25,12 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; -import java.util.UUID; public class AutoHost { - private static final String finalURL = "http://magmaguy.com:50000/"; - private static final UUID pluginRSPUUID = UUID.randomUUID(); + private static final String finalURL = "http://magmaguy.com:50000/"; + private static boolean done = false; +// private static final String finalURL = "http://localhost:50000/"; + private static BukkitTask keepAlive = null; @Getter private static String rspUUID = null; @@ -37,7 +40,7 @@ private AutoHost() { } public static void sendResourcePack(Player player) { - if (rspUUID == null) return; + if (rspUUID == null || !done) return; Logger.info("Sending resource pack to " + player.getName()); player.setResourcePack(finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); } @@ -80,7 +83,10 @@ public void run() { private static void checkFileExistence() { initializeLink(); - if (rspUUID == null) return; + if (rspUUID == null) { + Logger.info("No resource pack found on the server! Uploading resource pack to the server..."); + return; + } if (!sendSHA1()) uploadFile(); } @@ -93,11 +99,45 @@ public static void initializeLink() { try (CloseableHttpResponse response = httpClient.execute(httpPost)) { String responseString = EntityUtils.toString(response.getEntity()); - rspUUID = responseString.trim(); - DataConfig.setRspUUID(rspUUID); + int statusCode = response.getCode(); + + if (statusCode >= 200 && statusCode < 300) { + // Success - parse JSON response + try { + Gson gson = new Gson(); + JsonObject jsonResponse = gson.fromJson(responseString, JsonObject.class); + + // Check if response indicates success + if (jsonResponse.has("success") && jsonResponse.get("success").getAsBoolean()) { + rspUUID = jsonResponse.get("uuid").getAsString(); + DataConfig.setRspUUID(rspUUID); + Logger.info("Server initialized successfully: " + jsonResponse.get("message").getAsString()); + } else { + // Server returned error in success status code + Logger.warn("Server returned error in response: " + responseString); + rspUUID = null; + } + } catch (Exception e) { + // JSON parsing failed - validate if it looks like a UUID before using it + String trimmedResponse = responseString.trim(); + if (isValidUUID(trimmedResponse)) { + rspUUID = trimmedResponse; + DataConfig.setRspUUID(rspUUID); + Logger.info("Server initialized with UUID: " + rspUUID); + } else { + Logger.warn("Invalid response format from server: " + responseString); + rspUUID = null; + } + } + } else { + // Error - parse and log detailed error message + handleErrorResponse(responseString, statusCode, "initialization"); + rspUUID = null; + } } catch (Exception e) { Logger.warn("Failed to communicate with remote server!"); e.printStackTrace(); + rspUUID = null; } } catch (Exception e) { rspUUID = null; @@ -106,6 +146,23 @@ public static void initializeLink() { } } + // Helper method to validate UUID format + private static boolean isValidUUID(String uuidString) { + if (uuidString == null || uuidString.isEmpty()) { + return false; + } + + // Check if it looks like a UUID (basic validation) + // UUIDs are typically 36 characters with dashes or 32 characters without + String cleanUuid = uuidString.replaceAll("-", ""); + if (cleanUuid.length() != 32) { + return false; + } + + // Check if it contains only valid hex characters + return cleanUuid.matches("[0-9a-fA-F]+"); + } + public static void uploadFile() { Logger.info("Uploading resource!"); @@ -119,17 +176,28 @@ public static void uploadFile() { uploadFile.setEntity(builder.build()); try (CloseableHttpResponse response = httpClient.execute(uploadFile)) { + String responseString = EntityUtils.toString(response.getEntity()); + int statusCode = response.getCode(); + + if (statusCode >= 200 && statusCode < 300) { + Logger.info("Uploaded resource pack for automatic hosting! url: " + finalURL + "rsp_" + rspUUID); + done = true; + if (firstUpload) { + //Recover from a reload by sending the pack to online players + for (Player player : Bukkit.getOnlinePlayers()) + AutoHost.sendResourcePack(player); + } + firstUpload = false; + } else { + // Handle detailed error messages from server + handleErrorResponse(responseString, statusCode, "upload"); + return; + } } catch (Exception e) { - Logger.warn("Failed to communicate with remote server!"); + Logger.warn("Failed to communicate with remote server during upload!"); e.printStackTrace(); return; } - Logger.info("Uploaded resource pack for automatic hosting!"); - if (firstUpload) - //Recover from a reload by sending the pack to online players - for (Player player : Bukkit.getOnlinePlayers()) - AutoHost.sendResourcePack(player); - firstUpload = false; } catch (IOException e) { throw new RuntimeException(e); } @@ -146,21 +214,63 @@ private static boolean sendSHA1() { HttpEntity entity = builder.build(); httpPost.setEntity(entity); - // Convert the entity to a string for logging - ByteArrayOutputStream out = new ByteArrayOutputStream(); - entity.writeTo(out); - try (CloseableHttpResponse response = httpClient.execute(httpPost)) { String responseString = EntityUtils.toString(response.getEntity()); - return Boolean.valueOf(responseString); + int statusCode = response.getCode(); + + if (statusCode >= 200 && statusCode < 300) { + try { + // Parse JSON response + Gson gson = new Gson(); + JsonObject jsonResponse = gson.fromJson(responseString, JsonObject.class); + + // Check if response indicates success + if (jsonResponse.has("success") && jsonResponse.get("success").getAsBoolean()) { + boolean uploadNeeded = jsonResponse.get("uploadNeeded").getAsBoolean(); + + if (!uploadNeeded) { + Logger.info("Remote server already has this resource pack!"); + done = true; + if (firstUpload) { + //Recover from a reload by sending the pack to online players + for (Player player : Bukkit.getOnlinePlayers()) + AutoHost.sendResourcePack(player); + } + firstUpload = false; + } + return !uploadNeeded; // Return true if no upload needed + } else { + // Server returned error in success status code + Logger.warn("Server returned error in SHA1 response: " + responseString); + return false; + } + } catch (Exception e) { + // Fallback to boolean parsing (backward compatibility) + String trimmedResponse = responseString.trim(); + if (trimmedResponse.equals("true") || trimmedResponse.equals("false")) { + boolean result = Boolean.valueOf(trimmedResponse); + Logger.info("Remote server already has this resource pack! Response: " + responseString); + return result; + } else { + Logger.warn("Invalid SHA1 response format from server: " + responseString); + return false; + } + } + } else { + // Handle error response + handleErrorResponse(responseString, statusCode, "SHA1 check"); + return false; + } } catch (Exception e) { - Logger.warn("Failed to communicate with remote server!"); + Logger.warn("Failed to communicate with remote server during SHA1 check!"); e.printStackTrace(); + return false; } } catch (Exception e) { + Logger.warn("Failed to create HTTP client for SHA1 check!"); e.printStackTrace(); + return false; } - return false; } private static void sendStillAlive() throws IOException { @@ -172,8 +282,20 @@ private static void sendStillAlive() throws IOException { httpPost.setEntity(builder.build()); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String responseString = EntityUtils.toString(response.getEntity()); + int statusCode = response.getCode(); + + if (statusCode >= 200 && statusCode < 300) { + // Success - optionally log the success message + // Logger.info("Still alive ping successful"); + } else { + // Handle error - this might indicate session expired + handleErrorResponse(responseString, statusCode, "still alive"); + // Reset UUID to trigger re-initialization + rspUUID = null; + } } catch (Exception e) { - Logger.warn("Failed to communicate with remote server!"); + Logger.warn("Failed to communicate with remote server during still alive ping!"); e.printStackTrace(); } } @@ -216,5 +338,54 @@ public static void dataComplianceRequest() throws IOException { public static void shutdown() { if (keepAlive != null) keepAlive.cancel(); + done = false; + } + + private static void handleErrorResponse(String responseString, int statusCode, String operation) { + try { + Gson gson = new Gson(); + JsonObject errorResponse = gson.fromJson(responseString, JsonObject.class); + + if (errorResponse.has("error")) { + JsonObject error = errorResponse.getAsJsonObject("error"); + String errorCode = error.get("code").getAsString(); + String errorMessage = error.get("message").getAsString(); + String errorType = error.get("type").getAsString(); + + Logger.warn("=== Resource Pack " + operation.toUpperCase() + " ERROR ==="); + Logger.warn("Error Code: " + errorCode); + Logger.warn("Error Type: " + errorType); + Logger.warn("Message: " + errorMessage); + Logger.warn("HTTP Status: " + statusCode); + Logger.warn("====================================="); + + // Handle specific error types + switch (errorCode) { + case "MISSING_REQUIRED_FILES": + Logger.warn("Your resource pack structure is incorrect!"); + Logger.warn("Make sure pack.png and pack.mcmeta are in the root of your zip file."); + break; + case "FILE_TOO_LARGE": + Logger.warn("Your resource pack is too large! Please reduce the file size."); + break; + case "INVALID_FILE_FORMAT": + Logger.warn("Your resource pack file is corrupted or not a valid zip file."); + break; + case "SESSION_NOT_FOUND": + Logger.warn("Server session expired. Will attempt to reinitialize..."); + rspUUID = null; // Trigger re-initialization + break; + case "SERVER_UNAVAILABLE": + Logger.warn("Remote server is temporarily unavailable. Will retry later."); + break; + } + } else { + // Fallback for non-JSON error responses + Logger.warn("Server error during " + operation + " (HTTP " + statusCode + "): " + responseString); + } + } catch (Exception e) { + // Fallback if JSON parsing fails + Logger.warn("Server error during " + operation + " (HTTP " + statusCode + "): " + responseString); + } } } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java index 03966aa..3a8c9f4 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/BlueprintFolder.java @@ -1,8 +1,8 @@ package com.magmaguy.resourcepackmanager.config; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java index 919d8e0..d8b25a0 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DataConfig.java @@ -3,6 +3,8 @@ import com.magmaguy.magmacore.config.ConfigurationFile; import com.magmaguy.magmacore.util.Logger; +import java.util.UUID; + public class DataConfig extends ConfigurationFile { private static DataConfig instance = null; @@ -13,22 +15,81 @@ public DataConfig() { public static String getRspUUID() { String uuid = instance.getFileConfiguration().getString("uuid"); - if (uuid == null) uuid = ""; - return uuid; + + // If UUID exists but is invalid, clear it and return null + if (uuid != null && !uuid.isEmpty() && !isValidUUID(uuid)) { + Logger.warn("Invalid UUID found in config file: " + uuid + ". Deleting invalid UUID from file."); + instance.clearInvalidUUID(); + return null; + } + + // Return null for empty/null UUIDs instead of empty string + return (uuid == null || uuid.isEmpty()) ? "" : uuid; } public static void setRspUUID(String rspUUID) { + // Validate UUID if not null/empty + if (rspUUID != null && !rspUUID.isEmpty() && !isValidUUID(rspUUID)) { + throw new IllegalArgumentException("Invalid UUID format: " + rspUUID + + ". UUID must be in format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + } + + // Store null as null, not empty string instance.getFileConfiguration().set("uuid", rspUUID); try { instance.getFileConfiguration().save(instance.file); + if (rspUUID != null && !rspUUID.isEmpty()) { + Logger.info("Successfully saved UUID: " + rspUUID); + } else { + Logger.info("Successfully cleared UUID from config."); + } } catch (Exception e) { Logger.warn("Failed to save uuid!"); e.printStackTrace(); } } + /** + * Clears invalid UUID from config file + */ + private void clearInvalidUUID() { + getFileConfiguration().set("uuid", null); + try { + getFileConfiguration().save(file); + Logger.info("Invalid UUID cleared from config file."); + } catch (Exception e) { + Logger.warn("Failed to clear invalid UUID from config!"); + e.printStackTrace(); + } + } + + /** + * Validates if a string is a proper UUID format + * @param uuidString The string to validate + * @return true if valid UUID format, false otherwise + */ + private static boolean isValidUUID(String uuidString) { + if (uuidString == null || uuidString.trim().isEmpty()) { + return false; + } + + try { + // Use Java's built-in UUID validation + UUID.fromString(uuidString.trim()); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + @Override public void initializeValues() { - + // Validate existing UUID on initialization and clear if invalid + String existingUUID = getFileConfiguration().getString("uuid"); + if (existingUUID != null && !existingUUID.isEmpty() && !isValidUUID(existingUUID)) { + Logger.warn("Invalid UUID found in config file during initialization: " + existingUUID); + Logger.warn("Deleting invalid UUID from file. A new one will be generated on next server connection."); + clearInvalidUUID(); + } } -} +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfig.java new file mode 100644 index 0000000..b1223fe --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfig.java @@ -0,0 +1,19 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins; + +import com.magmaguy.magmacore.config.CustomConfig; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +public class CompatiblePluginConfig extends CustomConfig { + @Getter + private static Map compatiblePlugins = new HashMap<>(); + + public CompatiblePluginConfig() { + super("compatible_plugins", "com.magmaguy.resourcepackmanager.config.compatibleplugins.premade", CompatiblePluginConfigFields.class); + compatiblePlugins = new HashMap<>(); + for (String key : super.getCustomConfigFieldsHashMap().keySet()) + compatiblePlugins.put(key, (CompatiblePluginConfigFields) super.getCustomConfigFieldsHashMap().get(key)); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfigFields.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfigFields.java new file mode 100644 index 0000000..2f6b2f2 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/CompatiblePluginConfigFields.java @@ -0,0 +1,57 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins; + +import com.magmaguy.magmacore.config.CustomConfigFields; +import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; +import lombok.Getter; +import lombok.Setter; + +public class CompatiblePluginConfigFields extends CustomConfigFields { + + @Getter + @Setter + private String pluginName = "placeholder"; + @Getter + @Setter + private String url = null; + @Getter + @Setter + private String localPath = null; + @Getter + @Setter + private boolean encrypts = false; + @Getter + @Setter + private boolean distributes = false; + @Getter + @Setter + private boolean zips = true; + @Getter + @Setter + private String reloadCommand; + @Getter + @Setter + private boolean resourcePackUpdated = false; + @Getter + @Setter + private String mixerFilename; + + public CompatiblePluginConfigFields(String filename, boolean isEnabled) { + super(filename, isEnabled); + } + + @Override + public void processConfigFields() { + this.isEnabled = processBoolean("isEnabled", isEnabled, isEnabled, true); + this.pluginName = processString("pluginName", pluginName, pluginName, true); + this.url = processString("url", url, url, true); + this.encrypts = processBoolean("encrypts", encrypts, encrypts, true); + this.distributes = processBoolean("distributes", distributes, distributes, true); + this.zips = processBoolean("zips", zips, zips, true); + this.reloadCommand = processString("reloadCommand", reloadCommand, reloadCommand, true); + this.resourcePackUpdated = processBoolean("resourcePackUpdated", resourcePackUpdated, resourcePackUpdated, true); + this.mixerFilename = processString("mixerFilename", mixerFilename, mixerFilename, true); + this.localPath = processString("localPath", localPath, localPath, true); + + if (isEnabled) ThirdPartyResourcePack.initializeThirdPartyResourcePack(this); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BackpackPlus.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BackpackPlus.java new file mode 100644 index 0000000..d829860 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BackpackPlus.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class BackpackPlus extends CompatiblePluginConfigFields { + public BackpackPlus() { + super("backpack_plus", true); + setPluginName("BackpackPlus"); + setLocalPath("BackpackPlus" + File.separatorChar + "pack" + File.separatorChar + "resourcepack.zip"); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BetterHUD.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BetterHUD.java new file mode 100644 index 0000000..56235e9 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/BetterHUD.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class BetterHUD extends CompatiblePluginConfigFields { + public BetterHUD() { + super("better_hud", true); + setPluginName("BetterHUD"); + setLocalPath("BackpackPlus" + File.separatorChar + "pack" + File.separatorChar + "resourcepack.zip"); + setEncrypts(true); + setReloadCommand("betterhud reload"); + } +} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/EliteMobs.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/EliteMobs.java new file mode 100644 index 0000000..3db7b9a --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/EliteMobs.java @@ -0,0 +1,14 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class EliteMobs extends CompatiblePluginConfigFields { + public EliteMobs() { + super("elitemobs", true); + setPluginName("EliteMobs"); + setLocalPath("EliteMobs" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip"); + setReloadCommand("elitemobs reload"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/FreeMinecraftModels.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/FreeMinecraftModels.java new file mode 100644 index 0000000..44ab1f0 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/FreeMinecraftModels.java @@ -0,0 +1,14 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class FreeMinecraftModels extends CompatiblePluginConfigFields { + public FreeMinecraftModels() { + super("free_minecraft_models", true); + setPluginName("FreeMinecraftModels"); + setLocalPath("FreeMinecraftModels" + File.separatorChar + "output" + File.separatorChar + "FreeMinecraftModels.zip"); + setReloadCommand("freeminecraftmodels reload"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ItemsAdder.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ItemsAdder.java new file mode 100644 index 0000000..01b18d0 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ItemsAdder.java @@ -0,0 +1,15 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class ItemsAdder extends CompatiblePluginConfigFields { + public ItemsAdder() { + super("items_adder", true); + setPluginName("ItemsAdder"); + setLocalPath("ItemsAdder" + File.separatorChar + "output" + File.separatorChar + "generated.zip"); + setEncrypts(true); + setDistributes(true); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/MMOInventory.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/MMOInventory.java new file mode 100644 index 0000000..d357c0d --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/MMOInventory.java @@ -0,0 +1,11 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +public class MMOInventory extends CompatiblePluginConfigFields { + public MMOInventory() { + super("mmo_inventory", true); + setPluginName("MMOInventory"); + setUrl("https://www.dropbox.com/s/1lftxmzh0q4b5yu/mmoinv_rp_3.zip?dl=1"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ModelEngine.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ModelEngine.java new file mode 100644 index 0000000..d16a585 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ModelEngine.java @@ -0,0 +1,14 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class ModelEngine extends CompatiblePluginConfigFields { + public ModelEngine() { + super("model_engine", true); + setPluginName("ModelEngine"); + setLocalPath("ModelEngine" + File.separatorChar + "resource pack.zip"); + setReloadCommand("meg reload"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nova.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nova.java new file mode 100644 index 0000000..ce68b14 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nova.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class Nova extends CompatiblePluginConfigFields { + public Nova() { + super("nova", true); + setPluginName("Nova"); + setLocalPath("Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Oraxen.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Oraxen.java new file mode 100644 index 0000000..68ca0a5 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Oraxen.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class Oraxen extends CompatiblePluginConfigFields { + public Oraxen() { + super("oraxen", true); + setPluginName("Oraxen"); + setLocalPath("Oraxen" + File.separatorChar + "pack" + File.separatorChar + "pack.zip"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/RealisticSurvival.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/RealisticSurvival.java new file mode 100644 index 0000000..774f6f6 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/RealisticSurvival.java @@ -0,0 +1,11 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +public class RealisticSurvival extends CompatiblePluginConfigFields { + public RealisticSurvival() { + super("realistic_survival", true); + setPluginName("RealisticSurvival"); + setUrl("https://www.dropbox.com/scl/fi/5ggc7t20bfxmrzsbb1kok/Realistic-Survival-RP-1.2.8-RELEASE.zip?rlkey=55llpn4zj146usfmm8okf1ier&dl=1"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ResourcePackManager.java new file mode 100644 index 0000000..b69b50a --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ResourcePackManager.java @@ -0,0 +1,14 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class ResourcePackManager extends CompatiblePluginConfigFields { + public ResourcePackManager() { + super("resource_pack_manager", true); + setPluginName("ResourcePackManager"); + setLocalPath("ResourcePackManager" + File.separatorChar + "blueprint" + File.separatorChar + "blueprint.zip"); + setReloadCommand("rspm reload"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ValhallaMMO.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ValhallaMMO.java new file mode 100644 index 0000000..e4a506b --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/ValhallaMMO.java @@ -0,0 +1,14 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class ValhallaMMO extends CompatiblePluginConfigFields { + public ValhallaMMO() { + super("valhalla_mmo", true); + setPluginName("ValhallaMMO"); + setLocalPath("ValhallaMMO" + File.separatorChar + "resourcepack"); + setZips(false); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/VaneCore.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/VaneCore.java new file mode 100644 index 0000000..da73fa3 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/VaneCore.java @@ -0,0 +1,12 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +public class VaneCore extends CompatiblePluginConfigFields { + public VaneCore() { + super("vane_core", true); + setPluginName("vane-core"); + setLocalPath("vane-resource-pack.zip"); + setDistributes(true); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java b/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java deleted file mode 100644 index bdd04bb..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/datacompliance/DataCompliance.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.magmaguy.resourcepackmanager.datacompliance; - -public class DataCompliance { -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java index 663c0e0..07a5d6b 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java @@ -1,7 +1,7 @@ -package com.magmaguy.resourcepackmanager.Listeners; +package com.magmaguy.resourcepackmanager.listeners; -import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; +import com.magmaguy.resourcepackmanager.commands.ReloadCommand; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 07eb578..092cd01 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -1,27 +1,29 @@ package com.magmaguy.resourcepackmanager.mixer; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.google.gson.*; import com.google.gson.stream.JsonReader; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.api.ResourcePackManagerAPI; import com.magmaguy.resourcepackmanager.config.DefaultConfig; -import com.magmaguy.resourcepackmanager.thirdparty.*; +import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; -import java.io.*; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; public class Mix { private static final String resourcePackName = "ResourcePackManager_RSP"; - private static HashMap priorities; private static List resourcePacks; private static List orderedResourcePacks; @Getter @@ -59,23 +61,9 @@ private static boolean initializeDefaultPluginFolders() { private static void initializeThirdPartyResourcePacks() { orderedResourcePacks = new ArrayList<>(); - priorities = new HashMap<>(); // Use a mutable list so we can addAll() to it - List resourcePackManagers = new ArrayList<>(Arrays.asList( - new com.magmaguy.resourcepackmanager.thirdparty.ResourcePackManager(), - new EliteMobs(), - new FreeMinecraftModels(), - new ModelEngine(), - new ItemsAdder(), - new Nova(), - new Oraxen(), - new BetterHUD(), - new ValhallaMMO(), - new VaneCore(), - new BackpackPlus(), - new RealisticSurvival() - )); + List resourcePackManagers = new ArrayList<>(ThirdPartyResourcePack.thirdPartyResourcePacks.stream().toList()); // Add any API-registered packs resourcePackManagers.addAll(ResourcePackManagerAPI.thirdPartyResourcePackHashMap.values()); @@ -172,7 +160,7 @@ private static void cloneToOutputAndUnzip() { } catch (Exception e) { if (resourcePack == null) Logger.warn("Failed to extract resource pack! A file might be encrypted."); - else + else Logger.warn("Failed to extract resource pack " + resourcePack.getName() + " ! The file might be encrypted."); e.printStackTrace(); } @@ -191,7 +179,7 @@ private static void createOutputDefaultElements() { } List orderedFiles = new ArrayList<>(); - for (String filename : orderedResourcePacks){ + for (String filename : orderedResourcePacks) { orderedFiles.add(new File(getOutputFolder().getPath() + File.separatorChar + filename)); } @@ -211,18 +199,18 @@ private static void createOutputDefaultElements() { return; } - if (!DefaultConfig.getResourcePackRerouting().isEmpty() && !DefaultConfig.getResourcePackRerouting().isBlank()){ - try{ + if (!DefaultConfig.getResourcePackRerouting().isEmpty() && !DefaultConfig.getResourcePackRerouting().isBlank()) { + try { File rerouteFolder = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().getAbsolutePath() + File.separatorChar + DefaultConfig.getResourcePackRerouting()); if (!rerouteFolder.exists()) { Logger.warn("Failed to reroute zipped file to " + rerouteFolder.getAbsolutePath() + " because that folder does not exist!"); - } else if (!rerouteFolder.isDirectory()){ + } else if (!rerouteFolder.isDirectory()) { Logger.warn("Failed to reroute zipped file to " + rerouteFolder.getAbsolutePath() + " because that is a file and not a folder!"); } else if (!ZipFile.zip(getOutputResourcePackFolder(), rerouteFolder.getPath() + ".zip")) { Logger.warn("Failed to zip merged resource pack into reroute directory!"); return; } - } catch (Exception e){ + } catch (Exception e) { Logger.warn("Failed to reroute zipped file to " + DefaultConfig.getResourcePackRerouting()); } } @@ -388,497 +376,5 @@ private static JsonArray mergeJsonArrays(JsonArray array1, JsonArray array2) { return mergedArray; } -// -// @Getter -// private static File finalBedrockResourcePack; -// @Getter -// private static String finalBedrockSHA1; -// -// // Call this method in createOutputDefaultElements() after finalResourcePack is set -// private static void generateBedrockResourcePack() { -// if (finalResourcePack == null) { -// Logger.warn("Cannot generate Bedrock resource pack - Java resource pack was not created successfully!"); -// return; -// } -// -// Logger.info("Starting Bedrock resource pack generation..."); -// -// File bedrockOutputFolder = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + resourcePackName + "_Bedrock"); -// -// // Clean up any existing Bedrock folder -// if (bedrockOutputFolder.exists()) { -// recursivelyDeleteDirectory(bedrockOutputFolder); -// } -// -// try { -// bedrockOutputFolder.mkdirs(); -// -// // Extract the Java resource pack to process it -// File tempJavaFolder = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + "temp_java_extract"); -// if (tempJavaFolder.exists()) { -// recursivelyDeleteDirectory(tempJavaFolder); -// } -// tempJavaFolder.mkdirs(); -// -// ZipFile.unzip(finalResourcePack, tempJavaFolder); -// -// // Generate Bedrock pack contents -// generateBedrockManifest(bedrockOutputFolder); -// generateBehaviorPackManifest(bedrockOutputFolder); -// convertFreeMinecraftModelsAssets(tempJavaFolder, bedrockOutputFolder); -// -// // Create the Bedrock resource pack zip -// String bedrockPackName = resourcePackName + "_Bedrock.mcpack"; -// File bedrockZipFile = new File(getOutputFolder().getAbsolutePath() + File.separatorChar + bedrockPackName); -// -// if (ZipFile.zip(bedrockOutputFolder, bedrockZipFile.getAbsolutePath())) { -// finalBedrockResourcePack = bedrockZipFile; -// try { -// finalBedrockSHA1 = SHA1Generator.sha1CodeString(finalBedrockResourcePack); -// Logger.info("Successfully generated Bedrock resource pack: " + bedrockPackName); -// } catch (Exception e) { -// Logger.warn("Failed to generate SHA1 for Bedrock resource pack!"); -// } -// } else { -// Logger.warn("Failed to zip Bedrock resource pack!"); -// } -// -// // Clean up temporary folders -// recursivelyDeleteDirectory(tempJavaFolder); -// recursivelyDeleteDirectory(bedrockOutputFolder); -// -// } catch (Exception e) { -// Logger.warn("Failed to generate Bedrock resource pack!"); -// e.printStackTrace(); -// } -// } -// -// private static void generateBedrockManifest(File bedrockOutputFolder) { -// try { -// JsonObject manifest = new JsonObject(); -// manifest.addProperty("format_version", 2); -// -// // Header -// JsonObject header = new JsonObject(); -// header.addProperty("name", "FreeMinecraftModels Bedrock"); -// header.addProperty("description", "Bedrock Edition conversion of FreeMinecraftModels resource pack"); -// header.addProperty("uuid", UUID.randomUUID().toString()); -// JsonArray headerVersion = new JsonArray(); -// headerVersion.add(1); headerVersion.add(0); headerVersion.add(0); -// header.add("version", headerVersion); -// JsonArray minEngineVersion = new JsonArray(); -// minEngineVersion.add(1); minEngineVersion.add(21); minEngineVersion.add(0); -// header.add("min_engine_version", minEngineVersion); -// manifest.add("header", header); -// -// // Modules -// JsonArray modules = new JsonArray(); -// JsonObject resourceModule = new JsonObject(); -// resourceModule.addProperty("type", "resources"); -// resourceModule.addProperty("uuid", UUID.randomUUID().toString()); -// JsonArray moduleVersion = new JsonArray(); -// moduleVersion.add(1); moduleVersion.add(0); moduleVersion.add(0); -// resourceModule.add("version", moduleVersion); -// modules.add(resourceModule); -// manifest.add("modules", modules); -// -// // Write manifest.json -// File manifestFile = new File(bedrockOutputFolder, "manifest.json"); -// try (FileWriter writer = new FileWriter(manifestFile)) { -// new Gson().toJson(manifest, writer); -// } -// -// } catch (Exception e) { -// Logger.warn("Failed to generate Bedrock manifest!"); -// e.printStackTrace(); -// } -// } -// -// private static void generateBehaviorPackManifest(File bedrockOutputFolder) { -// try { -// JsonObject manifest = new JsonObject(); -// manifest.addProperty("format_version", 2); -// -// // Header -// JsonObject header = new JsonObject(); -// header.addProperty("name", "FreeMinecraftModels Bedrock Behavior"); -// header.addProperty("description", "Behavior pack for FreeMinecraftModels custom bone items"); -// header.addProperty("uuid", UUID.randomUUID().toString()); -// JsonArray headerVersion = new JsonArray(); -// headerVersion.add(1); headerVersion.add(0); headerVersion.add(0); -// header.add("version", headerVersion); -// JsonArray minEngineVersion = new JsonArray(); -// minEngineVersion.add(1); minEngineVersion.add(21); minEngineVersion.add(0); -// header.add("min_engine_version", minEngineVersion); -// manifest.add("header", header); -// -// // Modules -// JsonArray modules = new JsonArray(); -// JsonObject behaviorModule = new JsonObject(); -// behaviorModule.addProperty("type", "data"); -// behaviorModule.addProperty("uuid", UUID.randomUUID().toString()); -// JsonArray moduleVersion = new JsonArray(); -// moduleVersion.add(1); moduleVersion.add(0); moduleVersion.add(0); -// behaviorModule.add("version", moduleVersion); -// modules.add(behaviorModule); -// manifest.add("modules", modules); -// -// // Write BP manifest.json -// File bpFolder = new File(bedrockOutputFolder, "BP"); -// bpFolder.mkdirs(); -// File manifestFile = new File(bpFolder, "manifest.json"); -// try (FileWriter writer = new FileWriter(manifestFile)) { -// new Gson().toJson(manifest, writer); -// } -// -// } catch (Exception e) { -// Logger.warn("Failed to generate Behavior Pack manifest!"); -// e.printStackTrace(); -// } -// } -// -// private static void convertFreeMinecraftModelsAssets(File javaFolder, File bedrockFolder) { -// File freeMinecraftModelsAssets = new File(javaFolder, "assets" + File.separator + "freeminecraftmodels"); -// if (!freeMinecraftModelsAssets.exists()) { -// Logger.info("No FreeMinecraftModels assets found to convert"); -// return; -// } -// -// Logger.info("Converting FreeMinecraftModels assets to Bedrock format..."); -// -// try { -// // Create Bedrock directory structure -// File attachablesDir = new File(bedrockFolder, "attachables"); -// File modelsDir = new File(bedrockFolder, "models" + File.separator + "entity"); -// File texturesDir = new File(bedrockFolder, "textures" + File.separator + "entity"); -// -// attachablesDir.mkdirs(); -// modelsDir.mkdirs(); -// texturesDir.mkdirs(); -// -// // Copy textures first -// File javaTexturesDir = new File(freeMinecraftModelsAssets, "textures" + File.separator + "entity"); -// if (javaTexturesDir.exists()) { -// copyTexturesRecursively(javaTexturesDir, texturesDir); -// } -// -// // Convert Java models to Bedrock - each bone becomes separate item -// File javaModelsDir = new File(freeMinecraftModelsAssets, "models"); -// if (javaModelsDir.exists()) { -// convertJavaModelsToBedrock(javaModelsDir, attachablesDir, modelsDir, bedrockFolder); -// } -// -// } catch (Exception e) { -// Logger.warn("Failed to convert FreeMinecraftModels assets!"); -// e.printStackTrace(); -// } -// } -// -// private static void copyTexturesRecursively(File sourceDir, File targetDir) { -// if (!sourceDir.exists() || !sourceDir.isDirectory()) return; -// -// try { -// for (File file : sourceDir.listFiles()) { -// if (file.isDirectory()) { -// File newTargetDir = new File(targetDir, file.getName()); -// newTargetDir.mkdirs(); -// copyTexturesRecursively(file, newTargetDir); -// } else if (file.getName().endsWith(".png")) { -// File targetFile = new File(targetDir, file.getName()); -// Files.copy(file.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); -// } -// } -// } catch (Exception e) { -// Logger.warn("Failed to copy textures from " + sourceDir.getName()); -// e.printStackTrace(); -// } -// } -// -// private static void convertJavaModelsToBedrock(File javaModelsDir, File attachablesDir, File modelsDir, File bedrockFolder) { -// // Look for model folders (each model has its own folder with bone JSON files) -// for (File modelFolder : javaModelsDir.listFiles()) { -// if (!modelFolder.isDirectory()) continue; -// -// String modelName = modelFolder.getName(); -// -// // Skip equipment folder - that's for 1.21.4+ format -// if (modelName.equals("equipment")) continue; -// -// Logger.info("Converting model: " + modelName); -// -// try { -// // Process each bone file individually - each becomes a separate item -// convertModelBonesToBedrock(modelFolder, modelName, attachablesDir, modelsDir, bedrockFolder); -// -// } catch (Exception e) { -// Logger.warn("Failed to convert model: " + modelName); -// e.printStackTrace(); -// } -// } -// } -// -// private static void convertModelBonesToBedrock(File modelFolder, String modelName, File attachablesDir, File modelsDir, File bedrockFolder) { -// // Process each bone file as a separate item/geometry -// List boneFiles = new ArrayList<>(); -// collectBoneFiles(modelFolder, boneFiles); -// -// for (File boneFile : boneFiles) { -// String boneName = boneFile.getName().replace(".json", ""); -// -// // Skip the root bone -// if (boneName.equals("freeminecraftmodels_autogenerated_root")) continue; -// -// Logger.info("Converting bone: " + boneName + " from model: " + modelName); -// -// try { -// // Create unique identifiers for this bone -// String boneId = modelName + "_" + boneName; -// String itemId = "fmm_bone_" + boneId; -// -// // Convert bone to Bedrock geometry -// convertSingleBoneToBedrock(boneFile, boneName, modelName, modelsDir); -// -// // Create attachable for this bone -// generateBoneAttachable(itemId, boneName, modelName, attachablesDir); -// -// // Create behavior pack item for this bone -// generateBoneItem(itemId, boneName, modelName, bedrockFolder); -// -// } catch (Exception e) { -// Logger.warn("Failed to convert bone: " + boneName + " from model: " + modelName); -// e.printStackTrace(); -// } -// } -// } -// -// private static void collectBoneFiles(File folder, List boneFiles) { -// for (File file : folder.listFiles()) { -// if (file.isDirectory()) { -// collectBoneFiles(file, boneFiles); -// } else if (file.getName().endsWith(".json")) { -// boneFiles.add(file); -// } -// } -// } -// -// private static void convertSingleBoneToBedrock(File boneFile, String boneName, String modelName, File modelsDir) { -// try { -// // Read Java bone model -// JsonObject javaModel = JsonParser.parseReader(new FileReader(boneFile)).getAsJsonObject(); -// -// // Create Bedrock geometry -// JsonObject geometry = new JsonObject(); -// geometry.addProperty("format_version", "1.21.0"); -// -// JsonArray geometryArray = new JsonArray(); -// JsonObject geometryDef = new JsonObject(); -// -// JsonObject description = new JsonObject(); -// description.addProperty("identifier", "geometry.fmm_bone." + modelName + "_" + boneName); -// description.addProperty("texture_width", 64); -// description.addProperty("texture_height", 64); -// geometryDef.add("description", description); -// -// JsonArray bones = new JsonArray(); -// -// // Create root bone -// JsonObject rootBone = new JsonObject(); -// rootBone.addProperty("name", "root"); -// JsonArray pivot = new JsonArray(); -// pivot.add(0); pivot.add(0); pivot.add(0); -// rootBone.add("pivot", pivot); -// -// // Convert elements (cubes) to Bedrock format -// if (javaModel.has("elements")) { -// JsonArray elements = javaModel.getAsJsonArray("elements"); -// JsonArray cubes = new JsonArray(); -// -// for (int i = 0; i < elements.size(); i++) { -// JsonObject element = elements.get(i).getAsJsonObject(); -// JsonObject bedrockCube = convertJavaCubeToBedrock(element); -// if (bedrockCube != null) { -// cubes.add(bedrockCube); -// } -// } -// -// if (cubes.size() > 0) { -// rootBone.add("cubes", cubes); -// } -// } -// -// bones.add(rootBone); -// geometryDef.add("bones", bones); -// geometryArray.add(geometryDef); -// geometry.add("minecraft:geometry", geometryArray); -// -// // Write geometry file -// File geoFile = new File(modelsDir, "fmm_bone_" + modelName + "_" + boneName + ".geo.json"); -// try (FileWriter writer = new FileWriter(geoFile)) { -// new Gson().toJson(geometry, writer); -// } -// -// } catch (Exception e) { -// Logger.warn("Failed to convert bone: " + boneName); -// e.printStackTrace(); -// } -// } -// -// private static JsonObject convertJavaCubeToBedrock(JsonObject javaCube) { -// try { -// JsonObject bedrockCube = new JsonObject(); -// -// // Convert origin (from in Java) -// if (javaCube.has("from")) { -// JsonArray from = javaCube.getAsJsonArray("from"); -// JsonArray origin = new JsonArray(); -// origin.add(from.get(0)); -// origin.add(from.get(1)); -// origin.add(from.get(2)); -// bedrockCube.add("origin", origin); -// } -// -// // Convert size (to - from in Java) -// if (javaCube.has("from") && javaCube.has("to")) { -// JsonArray from = javaCube.getAsJsonArray("from"); -// JsonArray to = javaCube.getAsJsonArray("to"); -// JsonArray size = new JsonArray(); -// size.add(to.get(0).getAsDouble() - from.get(0).getAsDouble()); -// size.add(to.get(1).getAsDouble() - from.get(1).getAsDouble()); -// size.add(to.get(2).getAsDouble() - from.get(2).getAsDouble()); -// bedrockCube.add("size", size); -// } -// -// // Convert UV mapping - extract from faces -// if (javaCube.has("faces")) { -// JsonObject faces = javaCube.getAsJsonObject("faces"); -// // Use north face UV as default, or first available face -// JsonObject northFace = null; -// -// if (faces.has("north")) northFace = faces.getAsJsonObject("north"); -// else if (faces.has("south")) northFace = faces.getAsJsonObject("south"); -// else if (faces.has("east")) northFace = faces.getAsJsonObject("east"); -// else if (faces.has("west")) northFace = faces.getAsJsonObject("west"); -// else if (faces.has("up")) northFace = faces.getAsJsonObject("up"); -// else if (faces.has("down")) northFace = faces.getAsJsonObject("down"); -// -// if (northFace != null && northFace.has("uv")) { -// JsonArray javaUV = northFace.getAsJsonArray("uv"); -// JsonArray bedrockUV = new JsonArray(); -// bedrockUV.add(javaUV.get(0)); -// bedrockUV.add(javaUV.get(1)); -// bedrockCube.add("uv", bedrockUV); -// } else { -// // Default UV -// JsonArray uv = new JsonArray(); -// uv.add(0); uv.add(0); -// bedrockCube.add("uv", uv); -// } -// } -// -// return bedrockCube; -// -// } catch (Exception e) { -// Logger.warn("Failed to convert Java cube to Bedrock format"); -// return null; -// } -// } -// -// private static void generateBoneAttachable(String itemId, String boneName, String modelName, File attachablesDir) { -// try { -// JsonObject attachable = new JsonObject(); -// attachable.addProperty("format_version", "1.10.0"); -// -// JsonObject attachableData = new JsonObject(); -// JsonObject description = new JsonObject(); -// description.addProperty("identifier", "fmm:" + itemId); -// -// JsonObject materials = new JsonObject(); -// materials.addProperty("default", "entity_alphatest"); -// materials.addProperty("enchanted", "entity_alphatest_glint"); -// description.add("materials", materials); -// -// JsonObject textures = new JsonObject(); -// // Try to find appropriate texture path -// String texturePath = "textures/entity/" + modelName + "/texture"; -// textures.addProperty("default", texturePath); -// description.add("textures", textures); -// -// JsonObject geometry = new JsonObject(); -// geometry.addProperty("default", "geometry.fmm_bone." + modelName + "_" + boneName); -// description.add("geometry", geometry); -// -// // Configure for handheld/inventory item display -// JsonArray scripts = new JsonArray(); -// JsonObject animateScript = new JsonObject(); -// animateScript.addProperty("animate", "third_person_main_hand"); -// scripts.add(animateScript); -// description.add("scripts", scripts); -// -// attachableData.add("description", description); -// attachable.add("minecraft:attachable", attachableData); -// -// File attachableFile = new File(attachablesDir, itemId + ".json"); -// try (FileWriter writer = new FileWriter(attachableFile)) { -// new Gson().toJson(attachable, writer); -// } -// -// Logger.info("Created attachable: fmm:" + itemId); -// -// } catch (Exception e) { -// Logger.warn("Failed to generate attachable for " + itemId); -// e.printStackTrace(); -// } -// } -// -// private static void generateBoneItem(String itemId, String boneName, String modelName, File bedrockFolder) { -// try { -// // Create BP items folder -// File bpItemsDir = new File(bedrockFolder, "BP" + File.separator + "items"); -// bpItemsDir.mkdirs(); -// -// JsonObject item = new JsonObject(); -// item.addProperty("format_version", "1.21.0"); -// -// JsonObject minecraftItem = new JsonObject(); -// JsonObject description = new JsonObject(); -// description.addProperty("identifier", "fmm:" + itemId); -// description.addProperty("category", "Items"); -// minecraftItem.add("description", description); -// -// JsonObject components = new JsonObject(); -// -// // Set max stack size -// components.addProperty("minecraft:max_stack_size", 64); -// -// // Set icon - use leather horse armor for now -// components.addProperty("minecraft:icon", "leather_horse_armor"); -// -// // Set display name -// JsonObject displayName = new JsonObject(); -// displayName.addProperty("value", modelName + " " + boneName.replace("_", " ")); -// components.add("minecraft:display_name", displayName); -// -// // Set attachable for handheld items -// JsonObject attachable = new JsonObject(); -// attachable.addProperty("slot", "mainhand"); -// attachable.addProperty("attachable", "fmm:" + itemId); -// components.add("minecraft:attachable", attachable); -// -// minecraftItem.add("components", components); -// item.add("minecraft:item", minecraftItem); -// -// File itemFile = new File(bpItemsDir, itemId + ".json"); -// try (FileWriter writer = new FileWriter(itemFile)) { -// new Gson().toJson(item, writer); -// } -// -// Logger.info("Created custom bone item: fmm:" + itemId); -// -// } catch (Exception e) { -// Logger.warn("Failed to generate behavior pack item for " + itemId); -// e.printStackTrace(); -// } -// } - } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java deleted file mode 100644 index 95f41e1..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BackpackPlus.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class BackpackPlus extends ThirdPartyResourcePack { - public BackpackPlus() { - super("BackpackPlus", - "BackpackPlus" +File.separatorChar+ "pack" +File.separatorChar + "resourcepack.zip", - false, - false, - true, - true, - ""); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java deleted file mode 100644 index b1b19d8..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/BetterHUD.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class BetterHUD extends ThirdPartyResourcePack { - public BetterHUD() { - super("BetterHUD", - "BetterHud" + File.separatorChar + "build.zip", - true, - false, - true, - true, - "betterhud reload"); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java deleted file mode 100644 index 84903f7..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/EliteMobs.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class EliteMobs extends ThirdPartyResourcePack { - public EliteMobs() { - super("EliteMobs", - "EliteMobs" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip", - false, - false, - true, - true, - "elitemobs reload"); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java deleted file mode 100644 index 6b790a8..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/FreeMinecraftModels.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class FreeMinecraftModels extends ThirdPartyResourcePack { - public FreeMinecraftModels() { - super("FreeMinecraftModels", - "FreeMinecraftModels" + File.separatorChar + "output" + File.separatorChar + "FreeMinecraftModels.zip", - false, - false, - true, - true, - "freeminecraftmodels reload"); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java index a0c6e03..a3a3e38 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/GeneratorInterface.java @@ -1,8 +1,11 @@ package com.magmaguy.resourcepackmanager.thirdparty; public interface GeneratorInterface { - public void decrypt(); - public void unpublish(); - public void cloneResourcePackFile(); - public void reload(); + void decrypt(); + + void unpublish(); + + void cloneResourcePackFile(); + + void reload(); } diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java deleted file mode 100644 index a4b21e5..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ItemsAdder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class ItemsAdder extends ThirdPartyResourcePack { - public ItemsAdder() { - super("ItemsAdder", - "ItemsAdder" + File.separatorChar + "output" + File.separatorChar + "generated.zip", - false, - false, - true, - true, - ""); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java deleted file mode 100644 index 3323975..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/MMOInventory.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -public class MMOInventory extends ThirdPartyResourcePack { - public MMOInventory() { - super("MMOInventory", - "https://www.dropbox.com/s/1lftxmzh0q4b5yu/mmoinv_rp_3.zip?dl=1", - false, - false, - true, - false, - ""); - } -} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java deleted file mode 100644 index 1760ba1..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ModelEngine.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class ModelEngine extends ThirdPartyResourcePack { - public ModelEngine() { - super("ModelEngine", - "ModelEngine" + File.separatorChar + "resource pack.zip", - false, - false, - true, - true, - "meg reload"); - } -} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java deleted file mode 100644 index 13a017c..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Nova.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class Nova extends ThirdPartyResourcePack { - public Nova() { - super("Nova", - "Nova" + File.separatorChar + "resource_pack" + File.separatorChar + "ResourcePack.zip", - false, - false, - true, - true, - ""); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java deleted file mode 100644 index b828c09..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/Oraxen.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class Oraxen extends ThirdPartyResourcePack { - public Oraxen() { - super("Oraxen", - "Oraxen" + File.separatorChar + "pack" + File.separatorChar + "pack.zip", - false, - false, - true, - true, - ""); - } -} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java deleted file mode 100644 index c69eb94..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/RealisticSurvival.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -public class RealisticSurvival extends ThirdPartyResourcePack { - public RealisticSurvival() { - super("RealisticSurvival", - "https://www.dropbox.com/scl/fi/5ggc7t20bfxmrzsbb1kok/Realistic-Survival-RP-1.2.8-RELEASE.zip?rlkey=55llpn4zj146usfmm8okf1ier&dl=1", - false, - false, - true, - false, - ""); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java deleted file mode 100644 index a15d979..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ResourcePackManager.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class ResourcePackManager extends ThirdPartyResourcePack { - public ResourcePackManager() { - super("ResourcePackManager", - "ResourcePackManager" + File.separatorChar + "blueprint" + File.separatorChar + "blueprint.zip", - false, - false, - true, - true, - ""); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index 16f514e..d3fa686 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -1,9 +1,10 @@ package com.magmaguy.resourcepackmanager.thirdparty; -import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.magmacore.util.Logger; import com.magmaguy.magmacore.util.ZipFile; +import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DefaultConfig; +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; import org.apache.hc.client5.http.classic.methods.HttpGet; @@ -20,79 +21,124 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.HashSet; public class ThirdPartyResourcePack implements GeneratorInterface { + public static HashSet thirdPartyResourcePacks = new HashSet<>(); + @Getter private final String pluginName; @Getter + private final String mixerFilename; + private final String localPath; + private final String url; + @Getter private File file = null; - private String url; private boolean encrypts; private boolean distributes; private boolean zips; - private boolean local; private String reloadCommand; @Getter private boolean isEnabled; private String SHA1; - private boolean resourcePackUpdated = false; @Getter private File mixerResourcePack = null; @Getter - private String mixerFilename; - @Getter private int priority = -1; + @Getter + private boolean done = false; - public ThirdPartyResourcePack(String pluginName, String path, boolean encrypts, boolean distributes, boolean zips, boolean local, String reloadCommand) { + public ThirdPartyResourcePack(String pluginName, String localPath, String url, boolean encrypts, boolean distributes, boolean zips, String reloadCommand) { this.pluginName = pluginName; this.mixerFilename = pluginName + "_resource_pack.zip"; + this.url = url; + this.localPath = localPath; + isEnabled = Bukkit.getPluginManager().isPluginEnabled(pluginName); - if (isEnabled) - Logger.info("Initializing " + pluginName + "'s resource pack"); - else return; - this.local = local; - if (local) - this.file = new File(com.magmaguy.resourcepackmanager.ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + path); - else - this.url = path; - if (file != null && !file.exists()) { - Logger.warn("Found " + pluginName + " but could not find resource pack at location " + file.getPath() + " ! ResourcePackManager will not be able to merge the resource pack from this plugin."); + if (!isEnabled) { + done = true; + return; + } + + if (localPath != null && !processLocal(localPath)) { + done = true; + return; + } else if (localPath == null && url == null) { + Logger.warn("Plugin " + pluginName + " has no resource pack path specified! ResourcePackManager will not be able to merge the resource pack from this plugin."); isEnabled = false; + done = true; return; } + this.encrypts = encrypts; this.distributes = distributes; this.reloadCommand = reloadCommand; this.zips = zips; - if (!zips) { - ZipFile.zip(file, getTarget().toString()); - file = new File(getTarget().toUri()); - resourcePackUpdated = true; - mixerResourcePack = file; - } - if (isEnabled && local) SHA1 = getSHA1(file); + + if (!zips) zipThirdPartyPack(); + + if (localPath != null) SHA1 = getSHA1(file); + process(); + if (DefaultConfig.getPriorityOrder().contains(pluginName)) priority = DefaultConfig.getPriorityOrder().indexOf(pluginName); + + thirdPartyResourcePacks.add(this); + done = true; + } + + public static void shutdown() { + thirdPartyResourcePacks.clear(); + } + + public static void initializeThirdPartyResourcePack(CompatiblePluginConfigFields compatiblePluginConfigFields) { + new ThirdPartyResourcePack( + compatiblePluginConfigFields.getPluginName(), + compatiblePluginConfigFields.getLocalPath(), + compatiblePluginConfigFields.getUrl(), + compatiblePluginConfigFields.isEncrypts(), + compatiblePluginConfigFields.isDistributes(), + compatiblePluginConfigFields.isZips(), + compatiblePluginConfigFields.getReloadCommand()); + } + + private void zipThirdPartyPack() { + ZipFile.zip(file, getTarget().toString()); + file = new File(getTarget().toUri()); + mixerResourcePack = file; + } + + private boolean processLocal(String localPath) { + this.file = new File(ResourcePackManager.plugin.getDataFolder().getParentFile().toPath().toString() + File.separatorChar + localPath); + + if (!file.exists()) { + Logger.warn("Found " + pluginName + " but could not find resource pack at location " + file.getPath() + " ! ResourcePackManager will not be able to merge the resource pack from this plugin."); + isEnabled = false; + return false; + } + + return true; } public void process() { if (!isEnabled) return; - if (local && zips) { - if (mixerCloneExists()) { - if (getSHA1(new File(getTarget().toUri())).equals(SHA1)) { - mixerResourcePack = getTarget().toFile(); - return; - } else { - Logger.info("Clearing outdated resource pack in " + getTarget()); - getTarget().toFile().delete(); - } + + //Check if a copy already exists in the mixer folder and if it is up-to-date + if (localPath != null && mixerCloneExists()) { + if (getSHA1(new File(getTarget().toUri())).equals(SHA1)) { + mixerResourcePack = getTarget().toFile(); + return; + } else { + Logger.info("Clearing outdated resource pack in " + getTarget()); + getTarget().toFile().delete(); } } + if (encrypts) decrypt(); if (distributes) unpublish(); - if (zips) - cloneResourcePackFile(); + + cloneResourcePackFile(); } private String getSHA1(File file) { @@ -116,9 +162,8 @@ public void unpublish() { @Override public void cloneResourcePackFile() { - if (local) cloneLocalRSP(); + if (localPath != null) cloneLocalRSP(); else cloneRemoteRSP(); - resourcePackUpdated = true; } private void cloneLocalRSP() { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java deleted file mode 100644 index b7abf4d..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ValhallaMMO.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -import java.io.File; - -public class ValhallaMMO extends ThirdPartyResourcePack { - public ValhallaMMO() { - super("ValhallaMMO", - "ValhallaMMO" + File.separatorChar + "resourcepack", - false, - false, - false, - true, - ""); - } -} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java deleted file mode 100644 index 54b69bb..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/VaneCore.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.magmaguy.resourcepackmanager.thirdparty; - -public class VaneCore extends ThirdPartyResourcePack { - public VaneCore() { - super("vane-core", - "vane-resource-pack.zip", - false, - true, - true, - true, - ""); - } -} \ No newline at end of file diff --git a/src/main/resources/ReadMe.md b/src/main/resources/ReadMe.md index b7ca72c..15939ec 100644 --- a/src/main/resources/ReadMe.md +++ b/src/main/resources/ReadMe.md @@ -1,50 +1,73 @@ ### ResourcePackManager Data Policy and Compliance -**ResourcePackManager**, developed by MagmaGuy for the Nightbreak game studio, includes an optional auto-host feature that temporarily hosts resource pack data on a remote server. +**ResourcePackManager**, developed by MagmaGuy for the Nightbreak game studio, includes an optional auto-host feature +that temporarily hosts resource pack data on a remote server. -As of this writing, the hosted data is fully anonymous and serves the sole purpose of simplifying the distribution of resource packs to clients of servers utilizing this service. Future versions of this document may be updated to reflect any changes in data policy and other related matters. +As of this writing, the hosted data is fully anonymous and serves the sole purpose of simplifying the distribution of +resource packs to clients of servers utilizing this service. Future versions of this document may be updated to reflect +any changes in data policy and other related matters. This system complies with: + - **Directive 2000/31/EC** of the European Parliament and of the Council of 8 June 2000 - **Regulation (EU) 2022/2065** of the European Parliament and of the Council of 19 October 2022 -For data hosting transparency and compliance with these and other European norms, it is possible to obtain all data related to a server via the `/resourcepackmanager data_compliance_request` command. This command packages a full copy of all files and data associated with the requesting server. +For data hosting transparency and compliance with these and other European norms, it is possible to obtain all data +related to a server via the `/resourcepackmanager data_compliance_request` command. This command packages a full copy of +all files and data associated with the requesting server. -To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\nightbreak.io` (replace `/at\ ` with `@`). However, due to the system's design, data is only retained for up to 24h after a server using ResourcePackManager shuts down, making email requests largely unnecessary. Nonetheless, the option remains available to ensure full compliance with European norms. +To request the takedown of your server's data, contact MagmaGuy at `magmaguy/at\nightbreak.io` (replace `/at\ ` with +`@`). However, due to the system's design, data is only retained for up to 24h after a server using ResourcePackManager +shuts down, making email requests largely unnecessary. Nonetheless, the option remains available to ensure full +compliance with European norms. ### Data Handling by ResourcePackManager and Nightbreak Servers 1. **Resource Pack Creation** - - ResourcePackManager aggregates resource packs on your server into a single zipped file containing all custom content. + - ResourcePackManager aggregates resource packs on your server into a single zipped file containing all custom + content. 2. **Initialization Request** - - An initialization request is sent to remote servers, creating a `.txt` file with a random UUID. This file can be obtained via the `/resourcepackmanager data_compliance_request`. + - An initialization request is sent to remote servers, creating a `.txt` file with a random UUID. This file can be + obtained via the `/resourcepackmanager data_compliance_request`. 3. **SHA1 Request** - - ResourcePackManager transmits the SHA1 code of your resource pack to the remote server, which is saved in the `.txt` file. + - ResourcePackManager transmits the SHA1 code of your resource pack to the remote server, which is saved in the + `.txt` file. 4. **File Transmission** - - The zipped resource pack file is sent to the remote server, assigned the same UUID as the `.txt` file. This file can be obtained through `/resourcepackmanager data_compliance_request` and verified to be identical to the original in your output folder, as it is not modified by the Nightbreak servers. + - The zipped resource pack file is sent to the remote server, assigned the same UUID as the `.txt` file. This file + can be obtained through `/resourcepackmanager data_compliance_request` and verified to be identical to the + original in your output folder, as it is not modified by the Nightbreak servers. 5. **"Still Alive" Ping** - - ResourcePackManager sends a "still alive" ping every 6 hours, transmitting the UUID to the server, which updates the timestamp in the `.txt` file. - - If no "still alive" ping is received for over 24 hours, all data associated with that UUID (the `.txt` file and the resource pack) is deleted from the Nightbreak servers. + - ResourcePackManager sends a "still alive" ping every 6 hours, transmitting the UUID to the server, which updates + the timestamp in the `.txt` file. + - If no "still alive" ping is received for over 24 hours, all data associated with that UUID (the `.txt` file + and the resource pack) is deleted from the Nightbreak servers. ### Data Policy -- **Pseudonymous Identification:** Nightbreak assigns a random UUID to your server's files each time the server reboots, ensuring no IP address or identifiable information is stored unless users manually add such information to their resource packs. +- **Pseudonymous Identification:** Nightbreak assigns a random UUID to your server's files each time the server reboots, + ensuring no IP address or identifiable information is stored unless users manually add such information to their + resource packs. - **No Download Logging:** Nightbreak does not log any data related to download requests by Minecraft clients. - **No Data Sales:** Data uploaded to Nightbreak is not, has never been, and will never be sold. -- **Compliance with Takedown Requests:** Nightbreak will comply with takedown requests from both server administrators and law enforcement agencies. -- **Automatic Data Removal:** All data associated with your server is automatically removed 24 hours after your server shuts down and is reuploaded on every restart for as long as ResourcePackManager is in use and using the auto-host feature. +- **Compliance with Takedown Requests:** Nightbreak will comply with takedown requests from both server administrators + and law enforcement agencies. +- **Automatic Data Removal:** All data associated with your server is automatically removed 24 hours after your server + shuts down and is reuploaded on every restart for as long as ResourcePackManager is in use and using the auto-host + feature. ### Terms of service -As of writing this, the hosting service is provided for free for all users of ResourcePackManager. +As of writing this, the hosting service is provided for free for all users of ResourcePackManager. -It is the user's responsibility to ensure that the data uploaded to servers is not illegal and complies with any Mojang TOS as defined in their EULA. +It is the user's responsibility to ensure that the data uploaded to servers is not illegal and complies with any Mojang +TOS as defined in their EULA. -Abusing the service to host material other than resource packages may result in a permanent denial of service for the offending IP. +Abusing the service to host material other than resource packages may result in a permanent denial of service for the +offending IP. The service may, at any time, cease or be modified in such a way that makes old versions unable to connect to it. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2b025a9..3982791 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,18 +1,18 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.4.1 +version: 1.5.0 api-version: 1.14 author: MagmaGuy softdepend: -- EliteMobs -- FreeMinecraftModels -- ModelEngine -- Nova -- Oraxen -- ItemsAdder -- BackpackPlus -- vane-core -- RealisticSurvival + - EliteMobs + - FreeMinecraftModels + - ModelEngine + - Nova + - Oraxen + - ItemsAdder + - BackpackPlus + - vane-core + - RealisticSurvival commands: resourcepackmanager: From 6e93ee06afd711ca539c17aa4d8b5139122a6abc Mon Sep 17 00:00:00 2001 From: MagmaGuy Date: Sun, 3 Aug 2025 01:43:19 +0100 Subject: [PATCH 14/17] Resource Pack Manager 1.6.0: - [New] New using SSL for connecting to the remote server. This is a breaking change in the system, servers will have to update to 1.6.0 or later to use the Auto Host feature. - [New] Added compatibility with InfiniteVehicles - [New] ResourcePackManager now passively checks for file changes in all compatible directories, and automatically updates the resource pack as they change. - This means that if a resource pack updates during runtime, ResourcePackManager will also update automatically without requiring a reload. - This system has a 3 second buffer time to check for file stability, giving other plugins the time to zip their files correctly. This means it should work with both sync and async zipping of third party plugins, and it should no longer be possible to accidentally only grab a partially zipped file. - [Critical fixes] A lot of back end fixes to make the system more reliable and less remanding with the uploads. --- pom.xml | 2 +- .../ResourcePackManager.java | 12 ++- .../autohost/AutoHost.java | 80 +++++++++++-------- .../premade/InfiniteVehicles.java | 13 +++ .../listeners/ResourcePackGeneratedEvent.java | 14 ---- .../resourcepackmanager/mixer/Mix.java | 6 +- .../thirdparty/ThirdPartyResourcePack.java | 56 +++++++++++++ src/main/resources/plugin.yml | 2 +- 8 files changed, 128 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/InfiniteVehicles.java delete mode 100644 src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java diff --git a/pom.xml b/pom.xml index fb306aa..c477c5a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.magmaguy ResourcePackManager - 1.5.0 + 1.6.0 17 diff --git a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java index bb174db..24e3adb 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/ResourcePackManager.java @@ -4,7 +4,6 @@ import com.magmaguy.magmacore.MagmaCore; import com.magmaguy.magmacore.command.CommandManager; import com.magmaguy.magmacore.util.Logger; -import com.magmaguy.resourcepackmanager.listeners.ResourcePackGeneratedEvent; import com.magmaguy.resourcepackmanager.autohost.AutoHost; import com.magmaguy.resourcepackmanager.commands.DataComplianceRequestCommand; import com.magmaguy.resourcepackmanager.commands.ReloadCommand; @@ -12,7 +11,6 @@ import com.magmaguy.resourcepackmanager.config.DataConfig; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfig; -import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.playermanager.PlayerManager; import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; import com.magmaguy.resourcepackmanager.utils.VersionChecker; @@ -39,17 +37,17 @@ public void onEnable() { new DataConfig(); new DefaultConfig(); new CompatiblePluginConfig(); + BlueprintFolder.initialize(); - Mix.initialize(); + //This starts a watchdog to see if the resource packs change and updates the mixer if htey do. + ThirdPartyResourcePack.startResourcePackChangeWatchdog(); if (DefaultConfig.isAutoHost()) Bukkit.getPluginManager().registerEvents(new PlayerManager(), this); CommandManager commandManager = new CommandManager(this, "resourcepackmanager"); commandManager.registerCommand(new ReloadCommand()); commandManager.registerCommand(new DataComplianceRequestCommand()); - if (Bukkit.getPluginManager().isPluginEnabled("FreeMinecraftModels")) - Bukkit.getPluginManager().registerEvents(new ResourcePackGeneratedEvent(), this); Bukkit.getPluginManager().registerEvents(new VersionChecker.VersionCheckerEvents(), this); - AutoHost.initialize(); +// AutoHost.initialize(); Metrics metrics = new Metrics(this, 22867); MagmaCore.checkVersionUpdate("118574", "https://www.spigotmc.org/resources/resource-pack-manager.118574/"); @@ -64,7 +62,7 @@ public void onLoad() { public void onDisable() { Logger.info("Disabling ResourcePackManager"); ThirdPartyResourcePack.shutdown(); - HandlerList.unregisterAll(this); AutoHost.shutdown(); + HandlerList.unregisterAll(this); } } \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java index b50be98..6e83625 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/autohost/AutoHost.java @@ -8,6 +8,7 @@ import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.mixer.Mix; import lombok.Getter; +import lombok.Setter; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; @@ -21,28 +22,34 @@ import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; public class AutoHost { - private static final String finalURL = "http://magmaguy.com:50000/"; - private static boolean done = false; -// private static final String finalURL = "http://localhost:50000/"; + private static final String finalURL = "https://magmaguy.com/rsp/"; + @Setter + private static boolean done = false; +// private static final String finalURL = "https://localhost:50000/"; private static BukkitTask keepAlive = null; @Getter private static String rspUUID = null; + @Setter private static boolean firstUpload = true; private AutoHost() { } public static void sendResourcePack(Player player) { + Logger.info("Sending resource pack to " + player.getName() + ". rspUUID is null: " + (rspUUID == null) + ". done: " + done + ". firstUpload: " + firstUpload + "."); if (rspUUID == null || !done) return; Logger.info("Sending resource pack to " + player.getName()); - player.setResourcePack(finalURL + "rsp_" + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); + player.setResourcePack(finalURL + rspUUID, Mix.getFinalSHA1Bytes(), DefaultConfig.getResourcePackPrompt(), DefaultConfig.isForceResourcePack()); } public static void initialize() { @@ -50,35 +57,33 @@ public static void initialize() { if (Mix.getFinalResourcePack() == null) return; Logger.info("Starting autohost!"); firstUpload = true; - new BukkitRunnable() { + done = false; + rspUUID = null; + if (keepAlive != null) keepAlive.cancel(); + + keepAlive = new BukkitRunnable() { + int counter = 0; + @Override public void run() { - checkFileExistence(); - keepAlive = new BukkitRunnable() { - int counter = 0; - - @Override - public void run() { - if (rspUUID != null) { - counter = 0; - try { - sendStillAlive(); - } catch (Exception e) { - rspUUID = null; - Logger.warn("Failed to autohost resource pack!"); - e.printStackTrace(); - } - } else { - checkFileExistence(); - if (rspUUID == null && counter % 10 == 0) { - Logger.warn("Failed to connect to remote server to autohost the resource pack!"); - } - counter++; - } + if (rspUUID != null) { + counter = 0; + try { + sendStillAlive(); + } catch (Exception e) { + rspUUID = null; + Logger.warn("Failed to autohost resource pack!"); + e.printStackTrace(); + } + } else { + checkFileExistence(); + if (rspUUID == null && counter % 10 == 0) { + Logger.warn("Failed to connect to remote server to autohost the resource pack!"); } - }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 6 * 60 * 60 * 20L); + counter++; + } } - }.runTaskAsynchronously(ResourcePackManager.plugin); + }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 0, 6 * 60 * 60 * 20L); } private static void checkFileExistence() { @@ -88,6 +93,16 @@ private static void checkFileExistence() { return; } if (!sendSHA1()) uploadFile(); + else { + //Case if the remote server already has the resource pack + done = true; + if (firstUpload) { + //Recover from a reload by sending the pack to online players + for (Player player : Bukkit.getOnlinePlayers()) + AutoHost.sendResourcePack(player); + } + firstUpload = false; + } } public static void initializeLink() { @@ -180,7 +195,7 @@ public static void uploadFile() { int statusCode = response.getCode(); if (statusCode >= 200 && statusCode < 300) { - Logger.info("Uploaded resource pack for automatic hosting! url: " + finalURL + "rsp_" + rspUUID); + Logger.info("Uploaded resource pack for automatic hosting! url: " + finalURL + rspUUID); done = true; if (firstUpload) { //Recover from a reload by sending the pack to online players @@ -191,12 +206,10 @@ public static void uploadFile() { } else { // Handle detailed error messages from server handleErrorResponse(responseString, statusCode, "upload"); - return; } } catch (Exception e) { Logger.warn("Failed to communicate with remote server during upload!"); e.printStackTrace(); - return; } } catch (IOException e) { throw new RuntimeException(e); @@ -339,6 +352,7 @@ public static void dataComplianceRequest() throws IOException { public static void shutdown() { if (keepAlive != null) keepAlive.cancel(); done = false; + rspUUID = null; } private static void handleErrorResponse(String responseString, int statusCode, String operation) { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/InfiniteVehicles.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/InfiniteVehicles.java new file mode 100644 index 0000000..18f2587 --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/InfiniteVehicles.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class InfiniteVehicles extends CompatiblePluginConfigFields { + public InfiniteVehicles() { + super("infinite_vehicles", true); + setPluginName("InfiniteVehicles"); + setLocalPath("InfiniteVehicles" + File.separatorChar + "InfiniteModelPack.zip"); + } +} \ No newline at end of file diff --git a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java b/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java deleted file mode 100644 index 07a5d6b..0000000 --- a/src/main/java/com/magmaguy/resourcepackmanager/listeners/ResourcePackGeneratedEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.magmaguy.resourcepackmanager.listeners; - -import com.magmaguy.freeminecraftmodels.events.ResourcePackGenerationEvent; -import com.magmaguy.resourcepackmanager.commands.ReloadCommand; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class ResourcePackGeneratedEvent implements Listener { - @EventHandler - public void onResourcePackGenerated(ResourcePackGenerationEvent event) { - ReloadCommand.reloadPlugin(Bukkit.getConsoleSender()); - } -} diff --git a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java index 092cd01..cd43a84 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/mixer/Mix.java @@ -6,6 +6,7 @@ import com.magmaguy.magmacore.util.ZipFile; import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.api.ResourcePackManagerAPI; +import com.magmaguy.resourcepackmanager.autohost.AutoHost; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.thirdparty.ThirdPartyResourcePack; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; @@ -37,11 +38,12 @@ public class Mix { private Mix() { } - public static void initialize() { + public static void mixResourcePacks() { if (!initializeDefaultPluginFolders()) return; initializeThirdPartyResourcePacks(); cloneToOutputAndUnzip(); createOutputDefaultElements(); + AutoHost.initialize(); } private static boolean initializeDefaultPluginFolders() { @@ -168,9 +170,11 @@ private static void cloneToOutputAndUnzip() { } private static void createOutputDefaultElements() { + //Clear old resource pack if (getOutputResourcePackFolder().exists()) { recursivelyDeleteDirectory(getOutputResourcePackFolder()); } + //Make sure new resource pack exists try { getOutputResourcePackFolder().mkdir(); } catch (Exception e) { diff --git a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java index d3fa686..4883e8a 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/thirdparty/ThirdPartyResourcePack.java @@ -5,14 +5,18 @@ import com.magmaguy.resourcepackmanager.ResourcePackManager; import com.magmaguy.resourcepackmanager.config.DefaultConfig; import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; +import com.magmaguy.resourcepackmanager.mixer.Mix; import com.magmaguy.resourcepackmanager.utils.SHA1Generator; import lombok.Getter; +import lombok.Setter; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.HttpEntity; import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; import java.io.BufferedInputStream; import java.io.File; @@ -22,6 +26,7 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.HashSet; +import java.util.Objects; public class ThirdPartyResourcePack implements GeneratorInterface { public static HashSet thirdPartyResourcePacks = new HashSet<>(); @@ -48,6 +53,11 @@ public class ThirdPartyResourcePack implements GeneratorInterface { @Getter private boolean done = false; + private int ticksWithoutChange = 0; + private boolean consideredStable = false; + @Setter + private boolean stableResourcePackSent = false; + public ThirdPartyResourcePack(String pluginName, String localPath, String url, boolean encrypts, boolean distributes, boolean zips, String reloadCommand) { this.pluginName = pluginName; this.mixerFilename = pluginName + "_resource_pack.zip"; @@ -88,8 +98,54 @@ public ThirdPartyResourcePack(String pluginName, String localPath, String url, b done = true; } + private static BukkitTask resourcePackChangeWatcher = null; + + public static void startResourcePackChangeWatchdog() { + resourcePackChangeWatcher = new BukkitRunnable() { + @Override + public void run() { + boolean readyToSend = true; + boolean stableAlreadySent = true; + for (ThirdPartyResourcePack thirdPartyResourcePack : thirdPartyResourcePacks) { + if (!thirdPartyResourcePack.isEnabled || thirdPartyResourcePack.file == null) continue; + if (!Objects.equals(thirdPartyResourcePack.getSHA1(thirdPartyResourcePack.file), thirdPartyResourcePack.SHA1)) { + thirdPartyResourcePack.ticksWithoutChange = 0; + thirdPartyResourcePack.SHA1 = thirdPartyResourcePack.getSHA1(thirdPartyResourcePack.file); + if (thirdPartyResourcePack.consideredStable) { + thirdPartyResourcePack.consideredStable = false; + thirdPartyResourcePack.stableResourcePackSent = false; + Logger.info("Resource pack for " + thirdPartyResourcePack.pluginName + " has changed, considering it unstable."); + } + } + if (!thirdPartyResourcePack.stableResourcePackSent) stableAlreadySent = false; + if (!thirdPartyResourcePack.consideredStable) readyToSend = false; + if (thirdPartyResourcePack.consideredStable) continue; + thirdPartyResourcePack.ticksWithoutChange++; + if (thirdPartyResourcePack.ticksWithoutChange == 3) { + //Is nothing has changed for 1 second, then it should be considered to be stable + thirdPartyResourcePack.consideredStable = true; + Logger.info("Resource pack for " + thirdPartyResourcePack.pluginName + " has not changed for 3 seconds, considering it stable."); + } + } + + if (!stableAlreadySent && readyToSend) { + Logger.info("All resource packs are stable, sending resource pack to players."); + tagAsResourcePackSent(); + Mix.mixResourcePacks(); + } + } + }.runTaskTimerAsynchronously(ResourcePackManager.plugin, 20, 20); + } + + public static void tagAsResourcePackSent(){ + for (ThirdPartyResourcePack thirdPartyResourcePack : thirdPartyResourcePacks) { + thirdPartyResourcePack.stableResourcePackSent = true; + } + } + public static void shutdown() { thirdPartyResourcePacks.clear(); + resourcePackChangeWatcher.cancel(); } public static void initializeThirdPartyResourcePack(CompatiblePluginConfigFields compatiblePluginConfigFields) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3982791..c66e772 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: ResourcePackManager main: com.magmaguy.resourcepackmanager.ResourcePackManager -version: 1.5.0 +version: 1.6.0 api-version: 1.14 author: MagmaGuy softdepend: From 28a0e57c917e95ea136caaba991e0b20d9743a14 Mon Sep 17 00:00:00 2001 From: RabbitTV <154371299+RabbitTV22@users.noreply.github.com> Date: Sat, 2 Aug 2025 22:30:02 -0400 Subject: [PATCH 15/17] Create Nexo.java --- .../config/compatibleplugins/premade/Nexo.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nexo.java diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nexo.java b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nexo.java new file mode 100644 index 0000000..552fc7b --- /dev/null +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/compatibleplugins/premade/Nexo.java @@ -0,0 +1,13 @@ +package com.magmaguy.resourcepackmanager.config.compatibleplugins.premade; + +import com.magmaguy.resourcepackmanager.config.compatibleplugins.CompatiblePluginConfigFields; + +import java.io.File; + +public class Nexo extends CompatiblePluginConfigFields { + public Nexo() { + super("nexo", true); + setPluginName("Nexo"); + setLocalPath("Nexo" + File.separatorChar + "pack" + File.separatorChar + "pack.zip"); + } +} From 4ca711e69d90dd2d97cef7bd8e9b46f41ecdf3d8 Mon Sep 17 00:00:00 2001 From: RabbitTV <154371299+RabbitTV22@users.noreply.github.com> Date: Sat, 2 Aug 2025 22:30:36 -0400 Subject: [PATCH 16/17] Update plugin.yml --- src/main/resources/plugin.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c66e772..e32d532 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -13,9 +13,10 @@ softdepend: - BackpackPlus - vane-core - RealisticSurvival + - Nexo commands: resourcepackmanager: aliases: - rspm - description: "Main command" \ No newline at end of file + description: "Main command" From 837d3660ad939cf3cee54bf33fa17e24dae78db8 Mon Sep 17 00:00:00 2001 From: RabbitTV <154371299+RabbitTV22@users.noreply.github.com> Date: Sat, 2 Aug 2025 22:31:55 -0400 Subject: [PATCH 17/17] Update DefaultConfig.java --- .../com/magmaguy/resourcepackmanager/config/DefaultConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java index 466c341..67c4d29 100644 --- a/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java +++ b/src/main/java/com/magmaguy/resourcepackmanager/config/DefaultConfig.java @@ -44,7 +44,8 @@ public void initializeValues() { "ValhallaMMO", "MMOInventory", "vane-core", - "RealisticSurvival")); + "RealisticSurvival", + "Nexo")); autoHost = ConfigurationEngine.setBoolean( List.of("Automatically host the resource pack on MagmaGuy's servers",