diff --git a/divinemc-server/minecraft-patches/features/0050-Density-Function-Compiler.patch b/divinemc-server/minecraft-patches/features/0050-Density-Function-Compiler.patch index c9c785a..7933d5b 100644 --- a/divinemc-server/minecraft-patches/features/0050-Density-Function-Compiler.patch +++ b/divinemc-server/minecraft-patches/features/0050-Density-Function-Compiler.patch @@ -12,9 +12,6 @@ datapacks (including vanilla generation) to JVM bytecode to increase performance by allowing JVM JIT to better optimize the code. All functions provided by vanilla are implemented. -Not all server will benefit performance from this feature, as it -can sometimes slow down chunk performance than speed it up - diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..b43b7e242ea0a4f87704853c03201144ce355565 100644 --- a/net/minecraft/util/CubicSpline.java diff --git a/patches/removed/1.21.5/server/0013-Clump-experience-orbs.patch b/divinemc-server/minecraft-patches/features/0051-Clump-experience-orbs.patch similarity index 68% rename from patches/removed/1.21.5/server/0013-Clump-experience-orbs.patch rename to divinemc-server/minecraft-patches/features/0051-Clump-experience-orbs.patch index 260b449..306890c 100644 --- a/patches/removed/1.21.5/server/0013-Clump-experience-orbs.patch +++ b/divinemc-server/minecraft-patches/features/0051-Clump-experience-orbs.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Clump experience orbs diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java -index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474673e8df8 100644 +index 81aa1a91a2ecda3053b22c2eb9e59f0ea2faf7b5..e441aac80736910dfa726788ee34fb1e8a73a1f4 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java -@@ -49,6 +49,10 @@ public class ExperienceOrb extends Entity { - @javax.annotation.Nullable +@@ -47,6 +47,10 @@ public class ExperienceOrb extends Entity { + @Nullable public java.util.UUID triggerEntityId; public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; + // DivineMC start - Clump experience orbs @@ -18,8 +18,8 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + // DivineMC end - Clump experience orbs private void loadPaperNBT(CompoundTag tag) { - if (!tag.contains("Paper.ExpData", net.minecraft.nbt.Tag.TAG_COMPOUND)) { -@@ -239,6 +243,28 @@ public class ExperienceOrb extends Entity { + CompoundTag expData = tag.getCompoundOrEmpty("Paper.ExpData"); +@@ -244,6 +248,28 @@ public class ExperienceOrb extends Entity { } private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) { @@ -28,7 +28,7 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + AABB aABB = AABB.ofSize(pos, 1.0D, 1.0D, 1.0D); + int id = level.getRandom().nextInt(40); + List list = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aABB, (experienceOrbx) -> canMerge(experienceOrbx, id, amount)); -+ if(!list.isEmpty()) { ++ if (!list.isEmpty()) { + ExperienceOrb experienceOrb = list.getFirst(); + java.util.Map clumpedMap = (experienceOrb).clumps$getClumpedMap(); + (experienceOrb).clumps$setClumpedMap(java.util.stream.Stream.of(clumpedMap, java.util.Collections.singletonMap(amount, 1)) @@ -47,22 +47,22 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + // DivineMC end - Clump experience orbs // Paper - TODO some other event for this kind of merge AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0); - int randomInt = level.getRandom().nextInt(40); -@@ -254,11 +280,11 @@ public class ExperienceOrb extends Entity { + int randomInt = level.getRandom().nextInt(io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA)); // Paper - Configure how many orb groups per area +@@ -259,11 +285,11 @@ public class ExperienceOrb extends Entity { } private boolean canMerge(ExperienceOrb orb) { -- return orb != this && canMerge(orb, this.getId(), this.value); -+ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() && !this.is(orb) : orb != this && canMerge(orb, this.getId(), this.value); // DivineMC - Clump experience orbs +- return orb != this && canMerge(orb, this.getId(), this.getValue()); ++ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() && !this.is(orb) : orb != this && ExperienceOrb.canMerge(orb, this.getId(), this.getValue()); // DivineMC - Clump experience orbs } private static boolean canMerge(ExperienceOrb orb, int amount, int other) { -- return !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.value == other; -+ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() : !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.value == other; // DivineMC - Clump experience orbs +- return !orb.isRemoved() && (orb.getId() - amount) % io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA) == 0 && orb.getValue() == other; // Paper - Configure how many orbs will merge together ++ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() : !orb.isRemoved() && (orb.getId() - amount) % io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA) == 0 && orb.getValue() == other; // Paper - Configure how many orbs will merge together // Canvas - optimize orbs } private void merge(ExperienceOrb orb) { -@@ -267,6 +293,18 @@ public class ExperienceOrb extends Entity { +@@ -272,6 +298,18 @@ public class ExperienceOrb extends Entity { return; } // Paper end - call orb merge event @@ -74,15 +74,15 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + clumps$setClumpedMap(java.util.stream.Stream.of(clumps$getClumpedMap(), otherMap) + .flatMap(map -> map.entrySet().stream()) + .collect(java.util.stream.Collectors.toMap(java.util.Map.Entry::getKey, java.util.Map.Entry::getValue, Integer::sum))); -+ orb.discard(EntityRemoveEvent.Cause.MERGE); // DivineMC - add Bukkit remove cause ++ orb.discard(); + return; + } + // DivineMC end - Clump experience orbs this.count = this.count + orb.count; this.age = Math.min(this.age, orb.age); - orb.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause -@@ -308,6 +346,13 @@ public class ExperienceOrb extends Entity { - compound.putInt("Value", this.value); // Paper - save as Integer + orb.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause +@@ -313,6 +351,13 @@ public class ExperienceOrb extends Entity { + compound.putInt("Value", this.getValue()); // Paper - save as Integer compound.putInt("Count", this.count); this.savePaperNBT(compound); // Paper + // DivineMC start - Clump experience orbs @@ -95,19 +95,19 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 } @Override -@@ -317,10 +362,51 @@ public class ExperienceOrb extends Entity { - this.value = compound.getInt("Value"); // Paper - load as Integer - this.count = Math.max(compound.getInt("Count"), 1); +@@ -322,10 +367,53 @@ public class ExperienceOrb extends Entity { + this.setValue(compound.getIntOr("Value", 0)); // Paper - load as Integer + this.count = compound.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1); this.loadPaperNBT(compound); // Paper + // DivineMC start - Clump experience orbs + java.util.Map map = new java.util.HashMap<>(); + if (compound.contains("clumpedMap")) { -+ CompoundTag clumpedMap = compound.getCompound("clumpedMap"); -+ for (String s : clumpedMap.getAllKeys()) { -+ map.put(Integer.parseInt(s), clumpedMap.getInt(s)); ++ CompoundTag clumpedMap = compound.getCompound("clumpedMap").orElseThrow(); ++ for (String s : clumpedMap.keySet()) { ++ map.put(Integer.parseInt(s), clumpedMap.getInt(s).orElseThrow()); + } + } else { -+ map.put(value, count); ++ map.put(this.getValue(), count); + } + + clumps$setClumpedMap(map); @@ -117,44 +117,42 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 @Override public void playerTouch(Player entity) { + // DivineMC start - Clump experience orbs -+ if(entity instanceof ServerPlayer && org.bxteam.divinemc.DivineConfig.clumpOrbs) { ++ if (entity instanceof ServerPlayer serverPlayer && org.bxteam.divinemc.DivineConfig.clumpOrbs && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { + entity.takeXpDelay = 0; + entity.take(this, 1); + -+ if(this.value != 0 || clumps$resolve()) { ++ if (this.getValue() != 0 || clumps$resolve()) { + java.util.concurrent.atomic.AtomicInteger toGive = new java.util.concurrent.atomic.AtomicInteger(); + clumps$getClumpedMap().forEach((value, amount) -> { + int actualValue = value; -+ -+ for(int i = 0; i < amount; i++) { ++ for (int i = 0; i < amount; i++) { + int leftOver = actualValue; -+ if(leftOver == actualValue) { ++ if (leftOver == actualValue) { + leftOver = this.repairPlayerItems((ServerPlayer) entity, actualValue); + } -+ if(leftOver > 0) { ++ if (leftOver > 0) { + toGive.addAndGet(leftOver); + } + } + }); -+ if(toGive.get() > 0) { ++ if (toGive.get() > 0) { + entity.giveExperiencePoints(toGive.get()); + } + } -+ this.discard(); ++ ++ this.count = 0; ++ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); ++ + return; + } -+ // DivineMC end - Clump experience orbs ++ // Canvas end if (entity instanceof ServerPlayer serverPlayer) { if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent - entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, this.level().purpurConfig.playerExpPickupDelay, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay -@@ -338,10 +424,57 @@ public class ExperienceOrb extends Entity { + entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, this.level().purpurConfig.playerExpPickupDelay, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur - Configurable player pickup exp delay +@@ -343,10 +431,60 @@ public class ExperienceOrb extends Entity { } } -- private int repairPlayerItems(ServerPlayer player, int value) { -- Optional randomItemWith = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith( // Purpur - Add option to mend the most damaged equipment first -- EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged -- ); + // DivineMC start - Clump experience orbs + public Optional clumps$captureCurrentEntry(Optional entry) { + clumps$currentEntry = entry; @@ -164,7 +162,7 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + public java.util.Map clumps$getClumpedMap() { + if (clumps$clumpedMap == null) { + clumps$clumpedMap = new java.util.HashMap<>(); -+ clumps$clumpedMap.put(this.value, 1); ++ clumps$clumpedMap.put(this.getValue(), 1); + } + + return clumps$clumpedMap; @@ -176,36 +174,42 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474 + } + + public boolean clumps$resolve() { -+ value = clumps$getClumpedMap().entrySet() ++ this.setValue(clumps$getClumpedMap().entrySet() + .stream() + .map(entry -> entry.getKey() * entry.getValue()) + .reduce(Integer::sum) -+ .orElse(1); ++ .orElse(1)); + -+ return value > 0; ++ return this.getValue() > 0; + } ++ // DivineMC end - Clump experience orbs + -+ private int repairPlayerItems(ServerPlayer player, int amount) { -+ Optional randomItemWith = clumps$captureCurrentEntry(level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged)); // Purpur - Add option to mend the most damaged equipment first + private int repairPlayerItems(ServerPlayer player, int value) { +- Optional randomItemWith = level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith( // Purpur - Add option to mend the most damaged equipment first +- EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged +- ); ++ Optional randomItemWith = clumps$captureCurrentEntry(level().purpurConfig.useBetterMending ? EnchantmentHelper.getMostDamagedItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player) : EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged)); // Purpur - Add option to mend the most damaged equipment first // DivineMC - Clump experience orbs + ++ // DivineMC start - Clump experience orbs + if (org.bxteam.divinemc.DivineConfig.clumpOrbs) { + return clumps$currentEntry + .map(foundItem -> { + ItemStack itemstack = foundItem.itemStack(); -+ int xpToRepair = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemstack, (int) (amount * 1)); ++ int xpToRepair = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemstack, (int) (value * 1)); + int toRepair = Math.min(xpToRepair, itemstack.getDamageValue()); + itemstack.setDamageValue(itemstack.getDamageValue() - toRepair); -+ if(toRepair > 0) { -+ int used = amount - toRepair * amount / xpToRepair; -+ if(used > 0) { ++ if (toRepair > 0) { ++ int used = value - toRepair * value / xpToRepair; ++ if (used > 0) { + return this.repairPlayerItems(player, used); + } + } + return 0; + }) -+ .orElse(amount); ++ .orElse(value); + } -+ // DivineMC end - Clump experience orbs ++ // DivineMC end - Clump experience orbs ++ if (randomItemWith.isPresent()) { ItemStack itemStack = randomItemWith.get().itemStack(); int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemStack, value); diff --git a/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java b/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java index a224a2b..6b5fc89 100644 --- a/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java +++ b/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java @@ -247,10 +247,7 @@ public class DivineConfig { "This functionality compiles density functions from world generation", "datapacks (including vanilla generation) to JVM bytecode to increase", "performance by allowing JVM JIT to better optimize the code.", - "All functions provided by vanilla are implemented.", - "", - "Please test if this optimization actually benefits your server, as", - "it can sometimes slow down chunk performance than speed it up."); + "All functions provided by vanilla are implemented."); enableStructureLayoutOptimizer = getBoolean("settings.chunks.experimental.enable-structure-layout-optimizer", enableStructureLayoutOptimizer, "Enables a port of the mod StructureLayoutOptimizer, which optimizes general Jigsaw structure generation"); deduplicateShuffledTemplatePoolElementList = getBoolean("settings.chunks.experimental.deduplicate-shuffled-template-pool-element-list", deduplicateShuffledTemplatePoolElementList, @@ -264,6 +261,7 @@ public class DivineConfig { } public static boolean skipUselessSecondaryPoiSensor = true; + public static boolean clumpOrbs = true; public static boolean ignoreMovedTooQuicklyWhenLagging = true; public static boolean alwaysAllowWeirdMovement = true; public static boolean updateSuppressionCrashFix = true; @@ -278,6 +276,8 @@ public class DivineConfig { public static int hopperThrottleSkipTicks = 0; private static void miscSettings() { skipUselessSecondaryPoiSensor = getBoolean("settings.misc.skip-useless-secondary-poi-sensor", skipUselessSecondaryPoiSensor); + clumpOrbs = getBoolean("settings.misc.clump-orbs", clumpOrbs, + "Clumps experience orbs together to reduce entity count"); ignoreMovedTooQuicklyWhenLagging = getBoolean("settings.misc.ignore-moved-too-quickly-when-lagging", ignoreMovedTooQuicklyWhenLagging, "Improves general gameplay experience of the player when the server is lagging, as they won't get lagged back (message 'moved too quickly')"); alwaysAllowWeirdMovement = getBoolean("settings.misc.always-allow-weird-movement", alwaysAllowWeirdMovement,