diff --git a/patches/server/0090-Cache-CraftEntityType-minecraftToBukkit-convert.patch b/patches/server/0090-Cache-CraftEntityType-minecraftToBukkit-convert.patch new file mode 100644 index 000000000..7ecb7de52 --- /dev/null +++ b/patches/server/0090-Cache-CraftEntityType-minecraftToBukkit-convert.patch @@ -0,0 +1,234 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Sun, 28 Jul 2024 17:44:10 +0800 +Subject: [PATCH] Cache CraftEntityType#minecraftToBukkit convert + +The minecraftToBukkit EntityType convert call is expensive in mob spawn. This convert call is ued for spawn event call, +and the results are always same, thus there is no need to do the convert process every time, just cache it. +Save ~0.16ms per tick, and improve 11660ms -> 60ms in around 1 hour. + +diff --git a/src/main/java/net/minecraft/util/SpawnUtil.java b/src/main/java/net/minecraft/util/SpawnUtil.java +index 5c8e36ea8287029b1789719c687bac1a2c4c3a69..466e8213ded4c75d6240e4bf8ccd6ed9fb69dd39 100644 +--- a/src/main/java/net/minecraft/util/SpawnUtil.java ++++ b/src/main/java/net/minecraft/util/SpawnUtil.java +@@ -37,7 +37,7 @@ public class SpawnUtil { + // Paper start - PreCreatureSpawnEvent + com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + io.papermc.paper.util.MCUtil.toLocation(worldserver, blockposition), +- org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entitytypes), ++ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkitCached(entitytypes), // Leaf - Cache CraftEntityType#minecraftToBukkit convert + reason + ); + if (!event.callEvent()) { +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 6ac3dfab99cfb0b51c81cc20e71da1261a8c567c..992ce1076ac186ea21e1084624c31bd8077ab58b 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -442,7 +442,7 @@ public class EntityType implements FeatureElement, EntityTypeT + // Paper start - PreCreatureSpawnEvent + com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + io.papermc.paper.util.MCUtil.toLocation(worldserver, blockposition), +- org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this), ++ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkitCached(this), // Leaf - Cache CraftEntityType#minecraftToBukkit convert + spawnReason + ); + if (!event.callEvent()) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 967af8771ff8564c715d89f4b4b69b16c25add59..e7fafb3f919a7275212896c65a6eff682427ee34 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -137,7 +137,7 @@ public abstract class BaseSpawner { + // Paper start - PreCreatureSpawnEvent + com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + io.papermc.paper.util.MCUtil.toLocation(world, d0, d1, d2), +- org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(optional.get()), ++ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkitCached(optional.get()), // Leaf - Cache CraftEntityType#minecraftToBukkit convert + io.papermc.paper.util.MCUtil.toLocation(world, pos) + ); + if (!event.callEvent()) { +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index cf715114f0ebba449d7bd663445baec699d97537..7e1a007ed2f2c625f01fea210c9935cb02d119e0 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -344,7 +344,7 @@ public final class NaturalSpawner { + // Paper start - PreCreatureSpawnEvent + com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + io.papermc.paper.util.MCUtil.toLocation(world, pos), +- org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entitytypes), SpawnReason.NATURAL ++ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkitCached(entitytypes), SpawnReason.NATURAL // Leaf - Cache CraftEntityType#minecraftToBukkit convert + ); + if (!event.callEvent()) { + if (event.shouldAbortSpawn()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftStatistic.java b/src/main/java/org/bukkit/craftbukkit/CraftStatistic.java +index ccee1f637db5b8c34a5c125938edaa1361233e4d..a62f311e3f4dff63aa5c5d57ebc0bfa28c93b9b0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftStatistic.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftStatistic.java +@@ -187,7 +187,7 @@ public enum CraftStatistic { + + public static EntityType getEntityTypeFromStatistic(net.minecraft.stats.Stat> statistic) { + Preconditions.checkArgument(statistic != null, "NMS Statistic cannot be null"); +- return CraftEntityType.minecraftToBukkit(statistic.getValue()); ++ return CraftEntityType.minecraftToBukkitCached(statistic.getValue()); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + public static Material getMaterialFromStatistic(net.minecraft.stats.Stat statistic) { +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +index 146dde200845abcbe11015dda2c826a1aa711e42..881ce7c18efab9ef6f678be1a64afeaa3731b387 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +@@ -47,7 +47,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn()); +- return type.map(CraftEntityType::minecraftToBukkit).orElse(null); ++ return type.map(CraftEntityType::minecraftToBukkitCached).orElse(null); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + @Override +@@ -177,7 +177,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn()); +- return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null); ++ return type.map(CraftEntityType::minecraftToBukkitCached).map(CraftEntityType::bukkitToString).orElse(null); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftTrialSpawnerConfiguration.java b/src/main/java/org/bukkit/craftbukkit/block/CraftTrialSpawnerConfiguration.java +index 1e7a27bc783e68f9579d4d3c72ec165bde7175b9..72dfd388bb784009ac77ff0c93db56eb641c7ffc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftTrialSpawnerConfiguration.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftTrialSpawnerConfiguration.java +@@ -60,7 +60,7 @@ public class CraftTrialSpawnerConfiguration implements TrialSpawnerConfiguration + } + + Optional> type = net.minecraft.world.entity.EntityType.by(this.spawnPotentialsDefinition.unwrap().get(0).data().getEntityToSpawn()); +- return type.map(CraftEntityType::minecraftToBukkit).orElse(null); ++ return type.map(CraftEntityType::minecraftToBukkitCached).orElse(null); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +index 56bd3e3e7f36ee048526f3d0c7bf87d158a93fe6..5673f7bcdc75d2a8fc5fc143f18075103842c3d4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -83,7 +83,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + public CraftEntity(final CraftServer server, final Entity entity) { + this.server = server; + this.entity = entity; +- this.entityType = CraftEntityType.minecraftToBukkit(entity.getType()); ++ this.entityType = CraftEntityType.minecraftToBukkitCached(entity.getType()); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + this.taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this.entity.getServer(), this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run + } + +@@ -121,7 +121,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + } + +- CraftEntityTypes.EntityTypeData entityTypeData = CraftEntityTypes.getEntityTypeData(CraftEntityType.minecraftToBukkit(entity.getType())); ++ CraftEntityTypes.EntityTypeData entityTypeData = CraftEntityTypes.getEntityTypeData(CraftEntityType.minecraftToBukkitCached(entity.getType())); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + + if (entityTypeData != null) { + return (CraftEntity) entityTypeData.convertFunction().apply(server, entity); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityFactory.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityFactory.java +index b605924b96a9ec20bdccebdfa34067c1c1f95ada..32a0009c3c4f5fbb5ce3caa602416d253e5e87ab 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityFactory.java +@@ -35,7 +35,7 @@ public class CraftEntityFactory implements EntityFactory { + throw new IllegalArgumentException("Could not parse Entity: " + input); + } + +- return CraftEntitySnapshot.create(tag, CraftEntityType.minecraftToBukkit(type)); ++ return CraftEntitySnapshot.create(tag, CraftEntityType.minecraftToBukkitCached(type)); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + public static CraftEntityFactory instance() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntitySnapshot.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntitySnapshot.java +index 7b014b39e07decda09c6b0658a190bcd0b2504e8..3a012825e8f6700277b406f25ed7ed8995a7819c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntitySnapshot.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntitySnapshot.java +@@ -81,7 +81,7 @@ public class CraftEntitySnapshot implements EntitySnapshot { + } + + public static CraftEntitySnapshot create(CompoundTag tag) { +- EntityType type = net.minecraft.world.entity.EntityType.by(tag).map(CraftEntityType::minecraftToBukkit).orElse(null); ++ EntityType type = net.minecraft.world.entity.EntityType.by(tag).map(CraftEntityType::minecraftToBukkitCached).orElse(null); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + return CraftEntitySnapshot.create(tag, type); + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java +index 266b616419a47f518a43b990cc7cbb4516beda03..700c1f1fc2b87ad5aa4a5ff3f29124889ce9dfc3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java +@@ -13,6 +13,23 @@ import org.bukkit.entity.EntityType; + + public class CraftEntityType { + ++ // Leaf start - Cache CraftEntityType#minecraftToBukkit convert ++ public static final java.util.Map, EntityType> MINECRAFT_TO_BUKKIT_KEY_CACHE = new java.util.concurrent.ConcurrentHashMap<>(); ++ public static EntityType minecraftToBukkitCached(net.minecraft.world.entity.EntityType minecraft) { ++ if (org.dreeam.leaf.config.modules.opt.EnableCachedMTBEntityTypeConvert.enabled) { ++ EntityType asBukkit = MINECRAFT_TO_BUKKIT_KEY_CACHE.get(minecraft); ++ ++ if (asBukkit == null) { ++ asBukkit = minecraftToBukkit(minecraft); ++ MINECRAFT_TO_BUKKIT_KEY_CACHE.put(minecraft, asBukkit); ++ } ++ ++ return asBukkit; ++ } ++ ++ return minecraftToBukkit(minecraft); ++ } ++ // Leaf end - Cache CraftEntityType#minecraftToBukkit convert + public static EntityType minecraftToBukkit(net.minecraft.world.entity.EntityType minecraft) { + Preconditions.checkArgument(minecraft != null); + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +index e8ece01669373ecf6552d33b2ed72668524e2650..f862ad6acf769ec336b826b4bb248154cbebd35f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +@@ -29,7 +29,7 @@ final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMine + } + + Optional> type = net.minecraft.world.entity.EntityType.by(spawnData.getEntityToSpawn()); +- return type.map(CraftEntityType::minecraftToBukkit).orElse(null); ++ return type.map(CraftEntityType::minecraftToBukkitCached).orElse(null); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/tag/CraftEntityTag.java b/src/main/java/org/bukkit/craftbukkit/tag/CraftEntityTag.java +index 4270b771ff15d398b4788cb2fe27236989077614..97a87083f651434e51a9176009230e09301c3af2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/tag/CraftEntityTag.java ++++ b/src/main/java/org/bukkit/craftbukkit/tag/CraftEntityTag.java +@@ -21,6 +21,6 @@ public class CraftEntityTag extends CraftTag getValues() { +- return this.getHandle().stream().map(Holder::value).map(CraftEntityType::minecraftToBukkit).collect(Collectors.toUnmodifiableSet()); ++ return this.getHandle().stream().map(Holder::value).map(CraftEntityType::minecraftToBukkitCached).collect(Collectors.toUnmodifiableSet()); // Leaf - Cache CraftEntityType#minecraftToBukkit convert + } + } +diff --git a/src/main/java/org/dreeam/leaf/config/modules/opt/EnableCachedMTBEntityTypeConvert.java b/src/main/java/org/dreeam/leaf/config/modules/opt/EnableCachedMTBEntityTypeConvert.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0cab66307bc6892624c40d475e520c2b71a73d6d +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/config/modules/opt/EnableCachedMTBEntityTypeConvert.java +@@ -0,0 +1,18 @@ ++package org.dreeam.leaf.config.modules.opt; ++ ++import org.dreeam.leaf.config.ConfigModules; ++import org.dreeam.leaf.config.EnumConfigCategory; ++ ++public class EnableCachedMTBEntityTypeConvert extends ConfigModules { ++ ++ public String getBasePath() { ++ return EnumConfigCategory.PERF.getBaseKeyName(); ++ } ++ ++ public static boolean enabled = true; ++ ++ @Override ++ public void onLoaded() { ++ enabled = config.getBoolean(getBasePath() + ".enable-cached-minecraft-to-bukkit-entitytype-convert", enabled); ++ } ++}