From 6f77c43d97c810b652454eb3c73baebacc77a1c9 Mon Sep 17 00:00:00 2001 From: ceze88 Date: Mon, 17 Jul 2023 12:20:37 +0200 Subject: [PATCH] Fix item stacking when using large numbers --- .../listeners/item/ItemListeners.java | 15 +---- .../lootables/LootablesManager.java | 55 +++++++++++++------ .../settings/Settings.java | 4 +- .../stackable/entity/EntityStackImpl.java | 5 ++ .../item/StackedItemManagerImpl.java | 11 ++-- 5 files changed, 53 insertions(+), 37 deletions(-) diff --git a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/listeners/item/ItemListeners.java b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/listeners/item/ItemListeners.java index ccda0ba..57fe2b2 100644 --- a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/listeners/item/ItemListeners.java +++ b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/listeners/item/ItemListeners.java @@ -56,8 +56,6 @@ public class ItemListeners implements Listener { } } - //Do we need this? - @EventHandler public void onExist(ItemSpawnEvent event) { if (!Settings.STACK_ITEMS.getBoolean()) return; @@ -72,16 +70,7 @@ public class ItemListeners implements Listener { StringUtils.substring(itemStack.getItemMeta().getDisplayName(), 0, 3).equals("***")) { return; //Compatibility with Shop instance: https://www.spigotmc.org/resources/shop-a-simple-intuitive-shop-instance.9628/ } - - StackedItemManager itemStackManager = UltimateStackerApi.getStackedItemManager(); - - if (itemStackManager.isStackedItem(event.getEntity())) { - StackedItem stackedItem = UltimateStacker.getInstance().getStackedItemManager().getStackedItem(event.getEntity()); - stackedItem.setAmount(stackedItem.getAmount() + itemStack.getAmount()); - UltimateStackerApi.getStackedItemManager().createStack(event.getEntity(), UltimateStackerApi.getStackedItemManager().getActualItemAmount(event.getEntity()) + itemStack.getAmount()); - } else { - UltimateStackerApi.getStackedItemManager().createStack(event.getEntity(), itemStack.getAmount()); - } - + + UltimateStackerApi.getStackedItemManager().createStack(event.getEntity(), itemStack.getAmount()); } } diff --git a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/lootables/LootablesManager.java b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/lootables/LootablesManager.java index 3573c40..814b77a 100644 --- a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/lootables/LootablesManager.java +++ b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/lootables/LootablesManager.java @@ -27,6 +27,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; public class LootablesManager { @@ -36,6 +37,7 @@ public class LootablesManager { private final LootManager lootManager; private final String lootablesDir = UltimateStacker.getInstance().getDataFolder() + File.separator + "lootables"; + private final static int MAX_INT = Integer.MAX_VALUE/2; public LootablesManager() { this.lootables = new Lootables(lootablesDir); @@ -121,7 +123,6 @@ public class LootablesManager { double extraChance = looting / (looting + 1.0); - Random random = new Random(); boolean isCharged = entity instanceof Creeper && ((Creeper) entity).isPowered(); //Run main loot @@ -130,38 +131,56 @@ public class LootablesManager { if (loot.getOnlyDropFor().size() != 0 && loot.getOnlyDropFor().stream().noneMatch(type -> entity.getKiller() != null && type == entity.getKiller().getType())) continue; int finalLooting = loot.isAllowLootingEnchant() ? looting : 0; - int max = (int) (((loot.getMax() + finalLooting) * times) * (loot.getChance()/100)); - int min = (int) ((loot.getMin()) * times * (loot.getChance()/100)); + long max = (long) (((long) (loot.getMax() + finalLooting) * times) * (loot.getChance()/100 + (loot.isAllowLootingEnchant() ? extraChance : 0))); + long min = (long) ((loot.getMin()) * times * (loot.getChance()/100)); - int amount = random.nextInt((max - min) + 1) + min; + long amount = ThreadLocalRandom.current().nextLong((max - min) + 1) + min; if (amount > 0) { ItemStack item = entity.getFireTicks() > 0 ? loot.getBurnedMaterial() != null ? loot.getBurnedMaterial().parseItem() : loot.getMaterial().parseItem() - : loot.getMaterial().parseItem().clone(); - item.setAmount(amount); + : loot.getMaterial().parseItem(); + if (amount > MAX_INT) { + while (amount > MAX_INT) { + ItemStack loop = item.clone(); + loop.setAmount(MAX_INT); + amount -= MAX_INT; + toDrop.add(new Drop(loop)); + } + } + //Leftover + item.setAmount((int) amount); toDrop.add(new Drop(item)); } - } - //Run child loot - for (Loot loot : lootable.getRegisteredLoot().stream().filter(loot -> loot.getMaterial() == null).collect(Collectors.toList())) { + + //Run child loot //TODO: remove duplicated code for (Loot child : loot.getChildLoot()) { if (child.isRequireCharged() && !isCharged) continue; - if (loot.getOnlyDropFor().size() != 0 && loot.getOnlyDropFor().stream().noneMatch(type -> entity.getKiller() != null && type == entity.getKiller().getType())) continue; + if (child.getOnlyDropFor().size() != 0 && child.getOnlyDropFor().stream().noneMatch(type -> entity.getKiller() != null && type == entity.getKiller().getType())) continue; - int finalLooting = child.isAllowLootingEnchant() ? looting : 0; + int choildFinalLooting = child.isAllowLootingEnchant() ? looting : 0; - int max = (int) (((loot.getMax() + finalLooting) * times * (loot.getChance()/100))); - int min = (int) ((loot.getMin()) * times * (loot.getChance()/100)); - min = (int) (min - min*0.90); + long childMax = (long) (((long) (child.getMax() + finalLooting) * times) * (child.getChance()/100 + (child.isAllowLootingEnchant() ? extraChance : 0))); + long childmin = (long) ((child.getMin()) * times * (child.getChance()/100)); + childmin = (long) (childmin - childmin*0.90); - int amount = random.nextInt((max - min) + 1) + min; - if (amount > 0) { + long childamount = ThreadLocalRandom.current().nextLong((childMax - childmin) + 1) + childmin; + + if (childamount > 0) { ItemStack item = entity.getFireTicks() > 0 ? child.getBurnedMaterial() != null ? child.getBurnedMaterial().parseItem() : child.getMaterial().parseItem() - : child.getMaterial().parseItem().clone(); - item.setAmount(amount); + : child.getMaterial().parseItem(); + if (childamount > MAX_INT) { + while (childamount > MAX_INT) { + ItemStack loop = item.clone(); + loop.setAmount(MAX_INT); + childamount -= MAX_INT; + toDrop.add(new Drop(loop)); + } + } + //Leftover + item.setAmount((int) childamount); toDrop.add(new Drop(item)); } } diff --git a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/settings/Settings.java b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/settings/Settings.java index 3454c37..0956314 100644 --- a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/settings/Settings.java +++ b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/settings/Settings.java @@ -34,7 +34,7 @@ public class Settings implements com.craftaro.ultimatestacker.api.Settings { "The distance entities must be to each other in order to stack."); public static final ConfigSetting MAX_STACK_ENTITIES = new ConfigSetting(config, "Entities.Max Stack Size", 15, - "The max amount of entities in a single stack."); + "The max amount of entities in a single stack. Max value is 2000000000"); // Note: this setting is also referenced in EpicSpawners public static final ConfigSetting MIN_STACK_ENTITIES = new ConfigSetting(config, "Entities.Min Stack Amount", 5, @@ -183,7 +183,7 @@ public class Settings implements com.craftaro.ultimatestacker.api.Settings { "Should items that are blacklisted display holograms?"); public static final ConfigSetting MAX_STACK_ITEMS = new ConfigSetting(config, "Items.Max Stack Size", 512, - "The max stack size for items."); + "The max stack size for items. Max value is 1500000000"); public static final ConfigSetting NAME_FORMAT_ITEM = new ConfigSetting(config, "Items.Name Format", "&f{TYPE} &r[&6{AMT}x]", "The text displayed above a dropped item."); diff --git a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/entity/EntityStackImpl.java b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/entity/EntityStackImpl.java index 5059716..d7fbd96 100644 --- a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/entity/EntityStackImpl.java +++ b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/entity/EntityStackImpl.java @@ -1,10 +1,12 @@ package com.craftaro.ultimatestacker.stackable.entity; +import com.craftaro.core.SongodaCore; import com.craftaro.core.compatibility.ServerVersion; import com.craftaro.core.lootables.loot.Drop; import com.craftaro.core.lootables.loot.DropUtils; import com.craftaro.core.utils.EntityUtils; import com.craftaro.ultimatestacker.UltimateStacker; +import com.craftaro.ultimatestacker.api.UltimateStackerApi; import com.craftaro.ultimatestacker.api.events.entity.EntityStackKillEvent; import com.craftaro.ultimatestacker.api.stack.entity.EntityStack; import com.craftaro.ultimatestacker.settings.Settings; @@ -12,6 +14,7 @@ import com.craftaro.ultimatestacker.utils.Async; import com.craftaro.ultimatestacker.utils.Methods; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.LivingEntity; @@ -21,6 +24,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.util.Vector; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.UUID; diff --git a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/item/StackedItemManagerImpl.java b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/item/StackedItemManagerImpl.java index 3536deb..1a670f4 100644 --- a/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/item/StackedItemManagerImpl.java +++ b/UltimateStacker-Plugin/src/main/java/com.craftaro.ultimatestacker/stackable/item/StackedItemManagerImpl.java @@ -21,6 +21,8 @@ import java.util.concurrent.atomic.AtomicReference; public class StackedItemManagerImpl implements StackedItemManager { + private final static int MAX_INT = 1500000000; + @Override public @NotNull StackedItem getStackedItem(Item item) { return new StackedItemImpl(item); @@ -97,6 +99,7 @@ public class StackedItemManagerImpl implements StackedItemManager { } int maxItemStackSize = Settings.MAX_STACK_ITEMS.getInt(); + if (maxItemStackSize > MAX_INT) maxItemStackSize = MAX_INT; ItemStack fromItemStack = from.getItemStack(); ItemStack toItemStack = to.getItemStack(); @@ -104,7 +107,7 @@ public class StackedItemManagerImpl implements StackedItemManager { if (fromItemStack.getType() != toItemStack.getType()) return null; if (!ignoreRestrictions && UltimateStacker.isMaterialBlacklisted(fromItemStack)) return null; - int maxSize = UltimateStacker.getInstance().getItemFile().getInt("Items." + fromItemStack.getType().name() + ".Max Stack Size"); + long maxSize = UltimateStacker.getInstance().getItemFile().getInt("Items." + fromItemStack.getType().name() + ".Max Stack Size"); if (maxSize <= 0) { maxSize = maxItemStackSize; @@ -112,8 +115,8 @@ public class StackedItemManagerImpl implements StackedItemManager { maxSize = Math.min(maxSize, maxItemStackSize); } - int fromAmount = getActualItemAmount(from); - int toAmount = getActualItemAmount(to); + long fromAmount = getActualItemAmount(from); + long toAmount = getActualItemAmount(to); if (fromAmount + toAmount > maxSize) { if (callback != null) callback.accept(from, to, null); @@ -121,7 +124,7 @@ public class StackedItemManagerImpl implements StackedItemManager { //merge was unsuccessful return null; } else { - StackedItem merged = new StackedItemImpl(to, fromAmount + toAmount); + StackedItem merged = new StackedItemImpl(to, (int) (fromAmount + toAmount)); if (callback != null) callback.accept(null, to, merged); return merged; }