diff --git a/src/main/java/net/supremesurvival/supremecore/SupremeCore.java b/src/main/java/net/supremesurvival/supremecore/SupremeCore.java index 4c4a439..0c496f8 100644 --- a/src/main/java/net/supremesurvival/supremecore/SupremeCore.java +++ b/src/main/java/net/supremesurvival/supremecore/SupremeCore.java @@ -17,6 +17,7 @@ import net.supremesurvival.supremecore.mobUtils.HorseInfo; import net.supremesurvival.supremecore.sanguine.Vampire; import net.supremesurvival.supremecore.realestate.RealEstateCommand; +import net.supremesurvival.supremecore.loot.LootManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.event.Listener; @@ -31,6 +32,7 @@ public final class SupremeCore extends JavaPlugin implements Listener { IntervalAnnouncer intervalAnnouncer = new IntervalAnnouncer(this); FileHandler fileHandler = new FileHandler(this); Vampire vampire = new Vampire(this); + LootManager lootManager = new LootManager(this); @Override public void onEnable() { // Plugin startup logic @@ -46,6 +48,8 @@ public void onEnable() { Logger.sendMessage((ChatColor.YELLOW + "[SupremeCore] [+] " + ChatColor.GRAY + "SupremeCore loaded - Shit just got real."), Logger.LogType.INFO, "SupremeCore"); this.getServer().getPluginManager().registerEvents(new MobLoot(), this); Logger.sendMessage((ChatColor.YELLOW + "[SupremeCore] [+] " + ChatColor.GRAY + "SupremeNerf Gold Filter Loaded."), Logger.LogType.INFO, "SupremeCore"); + lootManager.enable(); + this.getServer().getPluginManager().registerEvents(lootManager, this); this.getCommand("HorseInfo").setExecutor(new HorseInfo()); this.getCommand("Landmarks").setExecutor(new LandmarkCommand()); this.getCommand("Vampire").setExecutor(vampire); diff --git a/src/main/java/net/supremesurvival/supremecore/loot/LootChest.java b/src/main/java/net/supremesurvival/supremecore/loot/LootChest.java index 7a9effc..8919148 100644 --- a/src/main/java/net/supremesurvival/supremecore/loot/LootChest.java +++ b/src/main/java/net/supremesurvival/supremecore/loot/LootChest.java @@ -1,4 +1,29 @@ package net.supremesurvival.supremecore.loot; +import org.bukkit.NamespacedKey; +import org.bukkit.block.BlockState; +import org.bukkit.block.TileState; +import org.bukkit.persistence.PersistentDataType; + public class LootChest { + private final TileState tileState; + private final NamespacedKey injectedKey; + + public LootChest(BlockState state, NamespacedKey injectedKey) { + if (!(state instanceof TileState tile)) { + throw new IllegalArgumentException("LootChest requires a TileState"); + } + this.tileState = tile; + this.injectedKey = injectedKey; + } + + public boolean hasInjectedLoot() { + Byte value = tileState.getPersistentDataContainer().get(injectedKey, PersistentDataType.BYTE); + return value != null && value == (byte) 1; + } + + public void markInjected() { + tileState.getPersistentDataContainer().set(injectedKey, PersistentDataType.BYTE, (byte) 1); + tileState.update(true, false); + } } diff --git a/src/main/java/net/supremesurvival/supremecore/loot/LootManager.java b/src/main/java/net/supremesurvival/supremecore/loot/LootManager.java index a70c22d..48f5bd1 100644 --- a/src/main/java/net/supremesurvival/supremecore/loot/LootManager.java +++ b/src/main/java/net/supremesurvival/supremecore/loot/LootManager.java @@ -1,4 +1,125 @@ package net.supremesurvival.supremecore.loot; -public class LootManager { +import net.supremesurvival.supremecore.SupremeCore; +import net.supremesurvival.supremecore.artefacts.Artefact; +import net.supremesurvival.supremecore.artefacts.ArtefactManager; +import net.supremesurvival.supremecore.commonUtils.Logger; +import net.supremesurvival.supremecore.commonUtils.fileHandler.ConfigUtility; +import net.supremesurvival.supremecore.tomes.Tome; +import net.supremesurvival.supremecore.tomes.TomeManager; +import org.bukkit.NamespacedKey; +import org.bukkit.block.BlockState; +import org.bukkit.block.Chest; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.Lootable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class LootManager implements Listener { + private static final String HANDLE = "Loot"; + + private final SupremeCore plugin; + private final Random random = new Random(); + private final NamespacedKey injectedKey; + + private double tomeChance; + private double artefactChance; + private int maxRollsPerChest; + private boolean requireLootTable; + + public LootManager(SupremeCore plugin) { + this.plugin = plugin; + this.injectedKey = new NamespacedKey(plugin, "loot_injected"); + } + + public void enable() { + FileConfiguration config = ConfigUtility.getModuleConfig("Loot"); + this.tomeChance = clampChance(config.getDouble("injection.tome-chance", 0.12)); + this.artefactChance = clampChance(config.getDouble("injection.artefact-chance", 0.04)); + this.maxRollsPerChest = Math.max(1, config.getInt("injection.max-rolls", 1)); + this.requireLootTable = config.getBoolean("injection.require-loot-table", true); + + Logger.sendMessage("Loot module enabled. tomeChance=" + tomeChance + ", artefactChance=" + artefactChance, + Logger.LogType.INFO, HANDLE); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryOpen(InventoryOpenEvent event) { + if (!(event.getPlayer() instanceof Player)) { + return; + } + + Inventory inventory = event.getInventory(); + if (!(inventory.getHolder() instanceof Chest chest)) { + return; + } + + BlockState state = chest.getBlock().getState(); + if (!(state instanceof Lootable lootable)) { + return; + } + + if (requireLootTable && lootable.getLootTable() == null) { + return; + } + + LootChest lootChest = new LootChest(state, injectedKey); + if (lootChest.hasInjectedLoot()) { + return; + } + + injectRandomLoot(inventory); + lootChest.markInjected(); + } + + private void injectRandomLoot(Inventory inventory) { + List rewards = new ArrayList<>(); + + for (int i = 0; i < maxRollsPerChest; i++) { + if (random.nextDouble() <= tomeChance) { + Tome tome = randomTome(); + if (tome != null) { + rewards.add(tome.getItem()); + } + } + if (random.nextDouble() <= artefactChance) { + Artefact artefact = randomArtefact(); + if (artefact != null) { + rewards.add(artefact.getItem()); + } + } + } + + for (ItemStack reward : rewards) { + inventory.addItem(reward); + } + } + + private Tome randomTome() { + if (TomeManager.tomes.isEmpty()) { + return null; + } + return TomeManager.tomes.get(random.nextInt(TomeManager.tomes.size())); + } + + private Artefact randomArtefact() { + if (ArtefactManager.artefacts.isEmpty()) { + return null; + } + return ArtefactManager.artefacts.get(random.nextInt(ArtefactManager.artefacts.size())); + } + + private double clampChance(double value) { + if (value < 0.0) return 0.0; + return Math.min(value, 1.0); + } } diff --git a/src/main/resources/Loot/config.yml b/src/main/resources/Loot/config.yml new file mode 100644 index 0000000..52412da --- /dev/null +++ b/src/main/resources/Loot/config.yml @@ -0,0 +1,12 @@ +injection: + # Chance (0.0 - 1.0) to inject one random tome per roll. + tome-chance: 0.12 + + # Chance (0.0 - 1.0) to inject one random artefact per roll. + artefact-chance: 0.04 + + # How many roll attempts happen on first valid open. + max-rolls: 1 + + # If true, only chests with a loot table (generated world chests) are targeted. + require-loot-table: true