Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import github.nighter.smartspawner.commands.list.gui.adminstacker.AdminStackerHandler;
import github.nighter.smartspawner.commands.list.gui.serverselection.ServerSelectionHandler;
import github.nighter.smartspawner.commands.prices.PricesGUI;
import github.nighter.smartspawner.config.Config;
import github.nighter.smartspawner.extras.HopperConfig;
import github.nighter.smartspawner.spawner.config.SpawnerSettingsConfig;
import github.nighter.smartspawner.spawner.config.ItemSpawnerSettingsConfig;
Expand Down Expand Up @@ -167,6 +168,7 @@ public class SmartSpawner extends JavaPlugin implements SmartSpawnerPlugin {
public void onEnable() {
long startTime = System.currentTimeMillis();
instance = this;
Config.load(this);

// Initialize version-specific components
initializeVersionComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.mojang.brigadier.context.CommandContext;
import github.nighter.smartspawner.SmartSpawner;
import github.nighter.smartspawner.commands.BaseSubCommand;
import github.nighter.smartspawner.config.Config;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.bukkit.command.CommandSender;
import org.jspecify.annotations.NullMarked;
Expand Down Expand Up @@ -54,6 +55,7 @@ private void reloadAll(CommandSender sender) {

// Reload all configurations
plugin.reloadConfig();
Config.reload(plugin);

// Reload components in dependency order
plugin.setUpHopperHandler();
Expand Down
30 changes: 30 additions & 0 deletions core/src/main/java/github/nighter/smartspawner/config/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package github.nighter.smartspawner.config;

import github.nighter.smartspawner.SmartSpawner;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.configuration.file.FileConfiguration;

@Getter
public class Config {
@Getter(AccessLevel.NONE)
private static volatile Config instance;

private final boolean optimizedLootgen;

private Config(FileConfiguration config) {
this.optimizedLootgen = config.getBoolean("loot_generation.optimized_generation");
}

public static Config get() {
return instance;
}

public static void reload(SmartSpawner plugin) {
load(plugin);
}

public static void load(SmartSpawner plugin) {
instance = new Config(plugin.getConfig());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import github.nighter.smartspawner.spawner.properties.SpawnerData;
import github.nighter.smartspawner.spawner.properties.VirtualInventory;
import github.nighter.smartspawner.utils.BlockPos;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
Expand Down Expand Up @@ -64,36 +65,47 @@ private void transferItems(Location hopperLoc, Location spawnerLoc) {
var state = hopperLoc.getBlock().getState(false);
if (!(state instanceof Hopper hopper)) return;

Map<Integer, ItemStack> displayItems = virtualInv.getDisplayInventory();
if (displayItems == null || displayItems.isEmpty()) return;

Inventory hopperInv = hopper.getInventory();

int transferred = 0;

int rangeStart = 0;
int rangeSize = Math.max(plugin.getHopperConfig().getStackPerTransfer(), 9);
List<ItemStack> removed = new ArrayList<>();

for (ItemStack item : displayItems.values()) {
if (transferred >= plugin.getHopperConfig().getStackPerTransfer()) break;
if (item == null || item.getType() == Material.AIR) continue;
while (transferred < plugin.getHopperConfig().getStackPerTransfer()) {
Int2ObjectMap<ItemStack> displayItems = virtualInv.getDisplayRange(rangeStart, rangeSize);
if (displayItems.isEmpty()) {
break;
}

for (ItemStack item : displayItems.values()) {
if (transferred >= plugin.getHopperConfig().getStackPerTransfer()) {
break;
}
if (item == null || item.getType() == Material.AIR) {
continue;
}

ItemStack clone = item.clone();
int originalAmount = clone.getAmount();
ItemStack clone = item.clone();
int originalAmount = clone.getAmount();

HashMap<Integer, ItemStack> leftovers = hopperInv.addItem(clone);
HashMap<Integer, ItemStack> leftovers = hopperInv.addItem(clone);

int insertedAmount = originalAmount;
int insertedAmount = originalAmount;

if (!leftovers.isEmpty()) {
insertedAmount -= leftovers.values().iterator().next().getAmount();
}
if (!leftovers.isEmpty()) {
insertedAmount -= leftovers.values().iterator().next().getAmount();
}

if (insertedAmount > 0) {
ItemStack toRemove = item.clone();
toRemove.setAmount(insertedAmount);
removed.add(toRemove);
transferred++;
if (insertedAmount > 0) {
ItemStack toRemove = item.clone();
toRemove.setAmount(insertedAmount);
removed.add(toRemove);
transferred++;
}
}

rangeStart += rangeSize;
}

if (!removed.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package github.nighter.smartspawner.language;

import github.nighter.smartspawner.SmartSpawner;
import github.nighter.smartspawner.utils.LRUCache;
import lombok.Getter;
import org.bukkit.ChatColor;
import org.bukkit.Material;
Expand All @@ -17,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.Normalizer;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import github.nighter.smartspawner.SmartSpawner;
import github.nighter.smartspawner.spawner.data.storage.SpawnerStorage;
import github.nighter.smartspawner.spawner.properties.ItemSignature;
import github.nighter.smartspawner.spawner.properties.SpawnerData;
import github.nighter.smartspawner.spawner.properties.VirtualInventory;
import github.nighter.smartspawner.Scheduler;
Expand Down Expand Up @@ -229,7 +230,7 @@ private boolean saveSpawnerBatch(Map<String, SpawnerData> spawners) {

VirtualInventory virtualInv = spawner.getVirtualInventory();
if (virtualInv != null) {
Map<VirtualInventory.ItemSignature, Long> items = virtualInv.getConsolidatedItems();
Map<ItemSignature, Long> items = virtualInv.getConsolidatedItems();
List<String> serializedItems = ItemStackSerializer.serializeInventory(items);
spawnerData.set(path + ".inventory", serializedItems);
}
Expand Down Expand Up @@ -436,13 +437,7 @@ private SpawnerData loadSpawnerFromConfig(String spawnerId, boolean logErrors, b
int amount = entry.getValue();

if (item != null && amount > 0) {
while (amount > 0) {
int batchSize = Math.min(amount, item.getMaxStackSize());
ItemStack batch = item.clone();
batch.setAmount(batchSize);
virtualInv.addItems(Collections.singletonList(batch));
amount -= batchSize;
}
virtualInv.addItem(item, amount);
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import github.nighter.smartspawner.commands.list.gui.CrossServerSpawnerData;
import github.nighter.smartspawner.spawner.data.storage.SpawnerStorage;
import github.nighter.smartspawner.spawner.data.storage.StorageMode;
import github.nighter.smartspawner.spawner.properties.ItemSignature;
import github.nighter.smartspawner.spawner.properties.SpawnerData;
import github.nighter.smartspawner.spawner.properties.VirtualInventory;
import github.nighter.smartspawner.spawner.utils.ItemStackSerializer;
Expand Down Expand Up @@ -595,7 +596,7 @@ private String serializeInventory(VirtualInventory virtualInv) {
return null;
}

Map<VirtualInventory.ItemSignature, Long> items = virtualInv.getConsolidatedItems();
Map<ItemSignature, Long> items = virtualInv.getConsolidatedItems();
if (items.isEmpty()) {
return null;
}
Expand Down Expand Up @@ -679,13 +680,7 @@ private void loadInventoryFromJson(String jsonData, VirtualInventory virtualInv)
int amount = entry.getValue();

if (item != null && amount > 0) {
while (amount > 0) {
int batchSize = Math.min(amount, item.getMaxStackSize());
ItemStack batch = item.clone();
batch.setAmount(batchSize);
virtualInv.addItems(Collections.singletonList(batch));
amount -= batchSize;
}
virtualInv.addItem(item, amount);
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package github.nighter.smartspawner.spawner.gui.main;

import github.nighter.smartspawner.spawner.properties.ItemSignature;
import net.kyori.adventure.text.Component;
import github.nighter.smartspawner.SmartSpawner;
import github.nighter.smartspawner.nms.VersionInitializer;
Expand Down Expand Up @@ -255,7 +256,7 @@ public ItemStack createLootStorageItem(SpawnerData spawner) {
}
List<Component> lootComponents = Collections.emptyList();
if (usedPlaceholders.contains("loot_items")) {
Map<VirtualInventory.ItemSignature, Long> storedItems = virtualInventory.getConsolidatedItems();
Map<ItemSignature, Long> storedItems = virtualInventory.getConsolidatedItems();
lootComponents = buildLootItemComponents(spawner.getEntityType(), storedItems);
}

Expand All @@ -282,11 +283,11 @@ public ItemStack createLootStorageItem(SpawnerData spawner) {
return chestItem;
}

private String buildLootItemsText(EntityType entityType, Map<VirtualInventory.ItemSignature, Long> storedItems) {
private String buildLootItemsText(EntityType entityType, Map<ItemSignature, Long> storedItems) {
// Create material-to-amount map for quick lookups
Map<Material, Long> materialAmountMap = new HashMap<>();
for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getTemplateRef().getType();
for (Map.Entry<ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getMaterial();
materialAmountMap.merge(material, entry.getValue(), Long::sum);
}

Expand Down Expand Up @@ -327,13 +328,12 @@ private String buildLootItemsText(EntityType entityType, Map<VirtualInventory.It
}
} else if (!storedItems.isEmpty()) {
// Sort items by name
List<Map.Entry<VirtualInventory.ItemSignature, Long>> sortedItems =
List<Map.Entry<ItemSignature, Long>> sortedItems =
new ArrayList<>(storedItems.entrySet());
sortedItems.sort(Comparator.comparing(e -> e.getKey().getMaterialName()));

for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : sortedItems) {
ItemStack templateItem = entry.getKey().getTemplateRef();
Material material = templateItem.getType();
for (Map.Entry<ItemSignature, Long> entry : sortedItems) {
Material material = entry.getKey().getMaterial();
long amount = entry.getValue();

String materialName = languageManager.getVanillaItemName(material);
Expand Down Expand Up @@ -602,10 +602,10 @@ private int calculatePercentage(long current, long maximum) {
return maximum > 0 ? (int) ((double) current / maximum * 100) : 0;
}

private List<Component> buildLootItemComponents(EntityType entityType, Map<VirtualInventory.ItemSignature, Long> storedItems) {
private List<Component> buildLootItemComponents(EntityType entityType, Map<ItemSignature, Long> storedItems) {
Map<Material, Long> materialAmountMap = new HashMap<>();
for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getTemplateRef().getType();
for (Map.Entry<ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getMaterial();
materialAmountMap.merge(material, entry.getValue(), Long::sum);
}

Expand All @@ -628,11 +628,11 @@ private List<Component> buildLootItemComponents(EntityType entityType, Map<Virtu
LOOT_ITEM_FORMAT_KEY, material, formattedAmount, chance));
}
} else {
List<Map.Entry<VirtualInventory.ItemSignature, Long>> sortedItems =
List<Map.Entry<ItemSignature, Long>> sortedItems =
new ArrayList<>(storedItems.entrySet());
sortedItems.sort(Comparator.comparing(e -> e.getKey().getMaterialName()));
for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : sortedItems) {
Material material = entry.getKey().getTemplateRef().getType();
for (Map.Entry<ItemSignature, Long> entry : sortedItems) {
Material material = entry.getKey().getMaterial();
long amount = entry.getValue();
String formattedAmount = languageManager.formatNumber(amount);
components.add(languageManager.buildTranslatableGuiLootLine(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package github.nighter.smartspawner.spawner.gui.sell;

import github.nighter.smartspawner.spawner.properties.ItemSignature;
import net.kyori.adventure.text.Component;
import github.nighter.smartspawner.SmartSpawner;
import github.nighter.smartspawner.language.LanguageManager;
Expand Down Expand Up @@ -164,7 +165,7 @@ private ItemStack createConfirmButton(Material material, Map<String, String> pla

private ItemStack createSpawnerInfoButton(Player player, SpawnerData spawner, Map<String, String> placeholders) {
// Build loot item components for {loot_items} placeholder
Map<VirtualInventory.ItemSignature, Long> storedItems = spawner.getVirtualInventory().getConsolidatedItems();
Map<ItemSignature, Long> storedItems = spawner.getVirtualInventory().getConsolidatedItems();
List<Component> lootComponents = buildSellInfoLootComponents(spawner, storedItems);

// Prepare the meta modifier consumer
Expand Down Expand Up @@ -200,10 +201,10 @@ private ItemStack createSpawnerInfoButton(Player player, SpawnerData spawner, Ma
return spawnerItem;
}

private List<Component> buildSellInfoLootComponents(SpawnerData spawner, Map<VirtualInventory.ItemSignature, Long> storedItems) {
private List<Component> buildSellInfoLootComponents(SpawnerData spawner, Map<ItemSignature, Long> storedItems) {
Map<Material, Long> materialAmountMap = new HashMap<>();
for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getTemplateRef().getType();
for (Map.Entry<ItemSignature, Long> entry : storedItems.entrySet()) {
Material material = entry.getKey().getMaterial();
materialAmountMap.merge(material, entry.getValue(), Long::sum);
}

Expand All @@ -227,10 +228,10 @@ private List<Component> buildSellInfoLootComponents(SpawnerData spawner, Map<Vir
"button_sell_info.loot_items", material, formattedAmount, chance));
}
} else {
List<Map.Entry<VirtualInventory.ItemSignature, Long>> sortedItems = new ArrayList<>(storedItems.entrySet());
List<Map.Entry<ItemSignature, Long>> sortedItems = new ArrayList<>(storedItems.entrySet());
sortedItems.sort(Comparator.comparing(e -> e.getKey().getMaterialName()));
for (Map.Entry<VirtualInventory.ItemSignature, Long> entry : sortedItems) {
Material material = entry.getKey().getTemplateRef().getType();
for (Map.Entry<ItemSignature, Long> entry : sortedItems) {
Material material = entry.getKey().getMaterial();
long amount = entry.getValue();
String formattedAmount = languageManager.formatNumber(amount);
components.add(languageManager.buildTranslatableGuiLootLine(
Expand Down
Loading
Loading