diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 351a17b..aa02c44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,6 +24,7 @@ jobs: - id: commit run: echo "short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - name: Delete existing release + if: github.ref != 'refs/heads/dev' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -52,5 +53,6 @@ jobs: name: RandomDrop ${{ steps.version.outputs.version }} files: ${{ steps.prepare.outputs.file }} prerelease: ${{ github.ref == 'refs/heads/dev' }} + generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 0670d50..2c5f031 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,4 @@ The configuration file is generated inside `plugins/RandomDrop/config.yml`. Nota - **KEEP_ITEM_CUSTOMNAME_ON_RANDOMIZE** – keep custom names when an item is randomized (default: `false`) - **CLAIM_CRAFTED_ITEMS** – mark crafted items as claimed (default: `true`) - **RANDOMIZE_CRAFT** – randomize crafting outputs (default: `true`) +- **PERSIST_LOOT_TABLE** – keep the randomized loot table across restarts (default: `true`) diff --git a/RandomDrop/pom.xml b/RandomDrop/pom.xml index da9fef4..8f5e585 100644 --- a/RandomDrop/pom.xml +++ b/RandomDrop/pom.xml @@ -4,7 +4,7 @@ com.theo546 RandomDrop - 0.0.0 + 1.1.0 jar RandomDrop diff --git a/RandomDrop/src/main/java/com/theo546/randomdrop/Main.java b/RandomDrop/src/main/java/com/theo546/randomdrop/Main.java index 18a7db0..99e11fb 100644 --- a/RandomDrop/src/main/java/com/theo546/randomdrop/Main.java +++ b/RandomDrop/src/main/java/com/theo546/randomdrop/Main.java @@ -1,6 +1,11 @@ // RandomDrop License | Copyright theo546 - github.com/theo546 package com.theo546.randomdrop; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -13,6 +18,7 @@ import org.bukkit.Material; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Item; import org.bukkit.inventory.ItemStack; @@ -29,8 +35,28 @@ public class Main extends JavaPlugin { public static boolean KEEP_ITEM_CUSTOMNAME_ON_RANDOMIZE; public static boolean CLAIM_CRAFTED_ITEMS; public static boolean RANDOMIZE_CRAFT; + public static boolean PERSIST_LOOT_TABLE; public static Map LOOT_TABLE; + private File getLootTableFile() { + String hash = sha256(String.valueOf(SEED)).substring(0, 16); + return new File(getDataFolder(), "loot_table_" + hash + ".yml"); + } + + private static String sha256(String input) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] encoded = digest.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for (byte b : encoded) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + @Override public void onEnable() { getConfig().addDefault("RANDOMIZE_DURABILITY", false); @@ -41,6 +67,7 @@ public void onEnable() { getConfig().addDefault("KEEP_ITEM_CUSTOMNAME_ON_RANDOMIZE", false); getConfig().addDefault("CLAIM_CRAFTED_ITEMS", true); getConfig().addDefault("RANDOMIZE_CRAFT", true); + getConfig().addDefault("PERSIST_LOOT_TABLE", true); getConfig().options().copyDefaults(true); saveConfig(); @@ -52,6 +79,7 @@ public void onEnable() { KEEP_ITEM_CUSTOMNAME_ON_RANDOMIZE = getConfig().getBoolean("KEEP_ITEM_CUSTOMNAME_ON_RANDOMIZE"); CLAIM_CRAFTED_ITEMS = getConfig().getBoolean("CLAIM_CRAFTED_ITEMS"); RANDOMIZE_CRAFT = getConfig().getBoolean("RANDOMIZE_CRAFT"); + PERSIST_LOOT_TABLE = getConfig().getBoolean("PERSIST_LOOT_TABLE"); initLootTable(); getServer().getPluginManager().registerEvents(new Listener(), this); @@ -59,6 +87,11 @@ public void onEnable() { private void initLootTable() { LOOT_TABLE = new HashMap<>(); + File file = getLootTableFile(); + if (PERSIST_LOOT_TABLE && !getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + World world = Bukkit.getWorlds().get(0); Location spawn = world.getSpawnLocation().clone(); spawn.setY(255); @@ -75,10 +108,44 @@ private void initLootTable() { } } + YamlConfiguration yaml = new YamlConfiguration(); + if (PERSIST_LOOT_TABLE && file.exists()) { + try { + yaml.load(file); + for (String key : yaml.getKeys(false)) { + Material k = Material.getMaterial(key); + Material v = Material.getMaterial(yaml.getString(key)); + if (k != null && v != null) { + LOOT_TABLE.put(k, v); + } + } + } catch (Exception e) { + getLogger().warning("Failed to load loot table: " + e.getMessage()); + } + } + List shuffled = new ArrayList<>(valid); Collections.shuffle(shuffled, new Random(SEED)); - for (int i = 0; i < valid.size(); i++) { - LOOT_TABLE.put(valid.get(i), shuffled.get(i)); + shuffled.removeAll(LOOT_TABLE.values()); + + boolean updated = false; + for (Material m : valid) { + if (!LOOT_TABLE.containsKey(m)) { + if (shuffled.isEmpty()) break; + LOOT_TABLE.put(m, shuffled.remove(0)); + updated = true; + } + } + + if (PERSIST_LOOT_TABLE && (updated || !file.exists())) { + for (Map.Entry entry : LOOT_TABLE.entrySet()) { + yaml.set(entry.getKey().name(), entry.getValue().name()); + } + try { + yaml.save(file); + } catch (IOException e) { + getLogger().warning("Failed to save loot table: " + e.getMessage()); + } } } diff --git a/RandomDrop/src/main/resources/plugin.yml b/RandomDrop/src/main/resources/plugin.yml index 8ec0268..61c0331 100644 --- a/RandomDrop/src/main/resources/plugin.yml +++ b/RandomDrop/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ main: com.theo546.randomdrop.Main name: RandomDrop -version: "1.0.6" +version: "1.1.0" api-version: 1.21 author: theo546 description: A Paper plugin to randomize the Minecraft loot table!