From aa4543936a8df0a30bd2f2ad7a52dd7bfad6e3a6 Mon Sep 17 00:00:00 2001 From: nostalgic853 Date: Sat, 22 Oct 2022 09:59:02 +0800 Subject: [PATCH] More optimizations --- patches/api/0002-Smooth-Teleports.patch | 34 ++ .../0008-Smarter-statistics-ticking.patch | 49 ++ patches/server/0009-Smooth-Teleports.patch | 61 +++ ...-Math.round-and-Math.hypot-functions.patch | 503 ++++++++++++++++++ patches/server/0011-Fast-speed-check.patch | 35 ++ 5 files changed, 682 insertions(+) create mode 100644 patches/api/0002-Smooth-Teleports.patch create mode 100644 patches/server/0008-Smarter-statistics-ticking.patch create mode 100644 patches/server/0009-Smooth-Teleports.patch create mode 100644 patches/server/0010-Optimize-Math.round-and-Math.hypot-functions.patch create mode 100644 patches/server/0011-Fast-speed-check.patch diff --git a/patches/api/0002-Smooth-Teleports.patch b/patches/api/0002-Smooth-Teleports.patch new file mode 100644 index 0000000..e673a84 --- /dev/null +++ b/patches/api/0002-Smooth-Teleports.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Sat, 13 Aug 2022 08:58:21 -0500 +Subject: [PATCH] Smooth Teleports + +Copyright (c) 2021 Tom Miller + +Original license: MIT +Original project: https://github.com/Cryptite/Slice + +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 9c2dcca0b6e34a3083226360575f0956a077d767..5ed16b78c39de21eff18a4824f84457a7c70fb58 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -2771,6 +2771,19 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + String getClientBrandName(); + // Paper end + ++ /** ++ * This abuses some of how Minecraft works and allows teleporting a player to another world without ++ * triggering typical respawn packets. All of natural state of chunk resends, entity adds/removes, etc still ++ * happen but the visual "refresh" of a world change is hidden. Depending on the destination location/world, ++ * this can act as a "smooth teleport" to a world if the new world is very similar looking to the old one. ++ * ++ * @param location New location to teleport this Player to ++ */ ++ // Slice start ++ @org.jetbrains.annotations.ApiStatus.Experimental ++ void teleportWithoutRespawn(Location location); ++ // Slice end ++ + // Paper start - Teleport API + /** + * Sets the player's rotation. diff --git a/patches/server/0008-Smarter-statistics-ticking.patch b/patches/server/0008-Smarter-statistics-ticking.patch new file mode 100644 index 0000000..b1c42bc --- /dev/null +++ b/patches/server/0008-Smarter-statistics-ticking.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mykyta Komarnytskyy +Date: Sat, 24 Oct 2020 21:03:53 -0500 +Subject: [PATCH] Smarter statistics ticking + +In vanilla, statistics that count time spent for an action (i.e. time played or sneak time) are incremented every tick. This is retarded. With this patch and a configured interval of 20, the statistics are only ticked every 20th tick and are incremented by 20 ticks at a time. This means a lot less ticking with the same accurate counting. +With an interval of 20, this patch saves roughly 3ms per tick on a server w/ 80 players online. + +Original code by YatopiaMC, licensed under MIT +You can find the original code on https://github.com/YatopiaMC/Yatopia + +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index e87a436711e179a4384630de41188c09a75a7f0d..97668eee40bff129c0a983a6596d0415ddb97b4b 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -315,19 +315,21 @@ public abstract class Player extends LivingEntity { + if (!this.level.isClientSide) { + this.foodData.tick(this); + this.wardenSpawnTracker.tick(); +- this.awardStat(Stats.PLAY_TIME); +- this.awardStat(Stats.TOTAL_WORLD_TIME); +- if (this.isAlive()) { +- this.awardStat(Stats.TIME_SINCE_DEATH); +- } +- +- if (this.isDiscrete()) { +- this.awardStat(Stats.CROUCH_TIME); +- } +- +- if (!this.isSleeping()) { +- this.awardStat(Stats.TIME_SINCE_REST); ++ // Mirai start ++ if (tickCount % 20 == 0) { ++ this.awardStat(Stats.PLAY_TIME, 20); ++ this.awardStat(Stats.TOTAL_WORLD_TIME, 20); ++ if (this.isAlive()) { ++ this.awardStat(Stats.TIME_SINCE_DEATH, 20); ++ } ++ if (this.isDiscrete()) { ++ this.awardStat(Stats.CROUCH_TIME, 20); ++ } ++ if (!this.isSleeping()) { ++ this.awardStat(Stats.TIME_SINCE_REST, 20); ++ } + } ++ // Mirai end + } + + int i = 29999999; diff --git a/patches/server/0009-Smooth-Teleports.patch b/patches/server/0009-Smooth-Teleports.patch new file mode 100644 index 0000000..6fa8145 --- /dev/null +++ b/patches/server/0009-Smooth-Teleports.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Sat, 13 Aug 2022 08:58:14 -0500 +Subject: [PATCH] Smooth Teleports + +Copyright (c) 2021 Tom Miller + +Original license: MIT +Original project: https://github.com/Cryptite/Slice + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 26d73eec3633cebc85972dbdeb14975d2dbb9b5b..882512d766bdd52fc6ada18db61d0e7e243ab039 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -271,6 +271,7 @@ public class ServerPlayer extends Player { + public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event ++ public boolean smoothWorldTeleport; // Slice + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, @Nullable ProfilePublicKey publicKey) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile, publicKey); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 3fb2323c89d04f1a545897a1e67f6f637f5ab9c1..393281223cd7b638d55b22ded20413709c23135a 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -961,12 +961,12 @@ public abstract class PlayerList { + } + // CraftBukkit start + LevelData worlddata = worldserver1.getLevelData(); +- entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag, entityplayer1.getLastDeathLocation())); ++ if (!entityplayer.smoothWorldTeleport) entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionTypeId(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag, entityplayer1.getLastDeathLocation())); // Slice + entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetSendDistance())); // Spigot // Paper - replace old player chunk management + entityplayer1.connection.send(new ClientboundSetSimulationDistancePacket(worldserver1.getChunkSource().chunkMap.playerChunkManager.getTargetTickViewDistance())); // Spigot // Paper - replace old player chunk management + entityplayer1.spawnIn(worldserver1); + entityplayer1.unsetRemoved(); +- entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); ++ if (!entityplayer.smoothWorldTeleport) entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); // Slice + entityplayer1.setShiftKeyDown(false); + + // entityplayer1.connection.teleport(entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot()); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 1ca26e7757fa8af885bfb3870128f8b48e0a7745..a06e0b8e0ba785f60ad2ed4a26fbd09d06c83540 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -1217,6 +1217,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + // Paper end + } + ++ // Slice start ++ public void teleportWithoutRespawn(Location location) { ++ ServerPlayer serverPlayer = getHandle(); ++ serverPlayer.smoothWorldTeleport = true; ++ teleport(location); ++ serverPlayer.smoothWorldTeleport = false; ++ } ++ // Slice end ++ + @Override + public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { + // Paper start - Teleport API diff --git a/patches/server/0010-Optimize-Math.round-and-Math.hypot-functions.patch b/patches/server/0010-Optimize-Math.round-and-Math.hypot-functions.patch new file mode 100644 index 0000000..fb0e3eb --- /dev/null +++ b/patches/server/0010-Optimize-Math.round-and-Math.hypot-functions.patch @@ -0,0 +1,503 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: etil2jz <81570777+etil2jz@users.noreply.github.com> +Date: Wed, 29 Jun 2022 02:17:00 +0200 +Subject: [PATCH] Optimize `Math.round` and `Math.hypot` functions + +Original license: MIT +Original project: https://github.com/fxmorin/carpet-fixes + +Copyright (c) 2020 Fx Morin + +diff --git a/src/main/java/carpetfixes/helpers/FastMath.java b/src/main/java/carpetfixes/helpers/FastMath.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1563b21eac06ba0cc57336a639a2d83accb511c9 +--- /dev/null ++++ b/src/main/java/carpetfixes/helpers/FastMath.java +@@ -0,0 +1,57 @@ ++package carpetfixes.helpers; ++ ++public class FastMath { ++ ++ private static final double HYPOT_MAX_MAG = 2^511; ++ private static final double HYPOT_FACTOR = 2^750; ++ ++ /** ++ * @author FX - PR0CESS ++ * ~1.25x faster than {@link Math#round(float)} ++ */ ++ public static int round(float a) { ++ return a > 0F ? (int)(a + .5F) : (int)(a - .5F); ++ } ++ ++ /** ++ * @author FX - PR0CESS ++ * ~1.28x faster than {@link Math#round(double)} ++ */ ++ public static long round(double a) { ++ return a > 0D ? (long)(a + .5D) : (long)(a - .5D); ++ } ++ ++ /** ++ * @author FX - PR0CESS ++ * Hypot implementation from the jafama library. Not 100% accurate! (3E-14%, 15 is perfectly accurate) ++ * ~1.6x faster than {@link Math#hypot(double,double)} ++ */ ++ public static double hypot(double x, double y) { ++ x = Math.abs(x); ++ y = Math.abs(y); ++ if (y < x) { // Ensuring x <= y ++ final double a = x; ++ x = y; ++ y = a; ++ } else if (!(y >= x)) { // Testing if we have some NaN ++ return x == Double.POSITIVE_INFINITY ? Double.POSITIVE_INFINITY : Double.NaN; ++ } ++ if (y-x == y) { // x too small to subtract from y ++ return y; ++ } else { ++ double factor; ++ if (y > HYPOT_MAX_MAG) { // y is too large: scaling down ++ x *= (1/HYPOT_FACTOR); ++ y *= (1/HYPOT_FACTOR); ++ factor = HYPOT_FACTOR; ++ } else if (x < (1/HYPOT_MAX_MAG)) { // x is too small: scaling up ++ x *= HYPOT_FACTOR; ++ y *= HYPOT_FACTOR; ++ factor = (1/HYPOT_FACTOR); ++ } else { ++ factor = 1.0; ++ } ++ return factor * Math.sqrt(x*x+y*y); ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +index f9251183df72ddc56662fd3f02acf21641a2200c..525bbe1a07025179cb32d9182fdde1d472b5852e 100644 +--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java +@@ -81,6 +81,6 @@ public class RAMDetails extends JList { + } + + private static String format(double tps) { +- return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); ++ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( carpetfixes.helpers.FastMath.round( tps * 100.0 ) / 100.0, 20.0 ); // Mirai + } + } +diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +index c3e54da4ab6440811aab2f9dd1e218802ac13285..db1319c51a5410ee106d023fce759f1e390872e2 100644 +--- a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java ++++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java +@@ -128,7 +128,7 @@ public class RAMGraph extends JComponent { + graphics.setColor(data.getLineColor()); + graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); + setToolTipText(String.format("Used: %s mb (%s%%)
%s", +- Math.round(data.getUsedMem() / 1024F / 1024F), ++ carpetfixes.helpers.FastMath.round(data.getUsedMem() / 1024F / 1024F), // Mirai + used, getTime(m.x))); + } + } +diff --git a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java +index dd501e83d991e45598509134fab05bafc1904953..5ecdbeb90e9715fc89ff25e9b3c33a2e8d98ff93 100644 +--- a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java ++++ b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java +@@ -387,11 +387,11 @@ public final class PlayerChunkLoader { + } + + protected long getTargetSendPerPlayerAddend() { +- return GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate <= 1.0 ? 0L : (long)Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate); ++ return GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate <= 1.0 ? 0L : (long)carpetfixes.helpers.FastMath.round(1.0e9 / GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate); // Mirai + } + + protected long getMaxSendAddend() { +- return GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate <= 1.0 ? 0L : (long)Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate); ++ return GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate <= 1.0 ? 0L : (long)carpetfixes.helpers.FastMath.round(1.0e9 / GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate); // Mirai + } + + public void onChunkPlayerTickReady(final int chunkX, final int chunkZ) { +diff --git a/src/main/java/io/papermc/paper/command/subcommands/FixLightCommand.java b/src/main/java/io/papermc/paper/command/subcommands/FixLightCommand.java +index 450bd95218852174cfbc88d4517e17daee5ffd5f..317e952655db5a4dcb2e6ec6573510f75bba9255 100644 +--- a/src/main/java/io/papermc/paper/command/subcommands/FixLightCommand.java ++++ b/src/main/java/io/papermc/paper/command/subcommands/FixLightCommand.java +@@ -95,12 +95,12 @@ public final class FixLightCommand implements PaperSubcommand { + ++relitChunks[0]; + sender.getBukkitEntity().sendMessage(text().color(DARK_AQUA).append( + text("Relit chunk ", BLUE), text(chunkPos.toString()), +- text(", progress: ", BLUE), text((int) (Math.round(100.0 * (double) (relitChunks[0]) / (double) pending[0])) + "%") ++ text(", progress: ", BLUE), text((int) (carpetfixes.helpers.FastMath.round(100.0 * (double) (relitChunks[0]) / (double) pending[0])) + "%") // Mirai + )); + }, + (final int totalRelit) -> { + final long end = System.nanoTime(); +- final long diff = Math.round(1.0e-6 * (end - start)); ++ final long diff = carpetfixes.helpers.FastMath.round(1.0e-6 * (end - start)); // Mirai + sender.getBukkitEntity().sendMessage(text().color(DARK_AQUA).append( + text("Relit ", BLUE), text(totalRelit), + text(" chunks. Took ", BLUE), text(diff + "ms") +diff --git a/src/main/java/net/minecraft/commands/arguments/TimeArgument.java b/src/main/java/net/minecraft/commands/arguments/TimeArgument.java +index e3e80db89c18588322ffdaa0f9fd85e398cb1471..d947011b80ee14e7aaf74af3d9081fc78e8cb4c3 100644 +--- a/src/main/java/net/minecraft/commands/arguments/TimeArgument.java ++++ b/src/main/java/net/minecraft/commands/arguments/TimeArgument.java +@@ -35,7 +35,7 @@ public class TimeArgument implements ArgumentType { + if (i == 0) { + throw ERROR_INVALID_UNIT.create(); + } else { +- int j = Math.round(f * (float)i); ++ int j = carpetfixes.helpers.FastMath.round(f * (float)i); // Mirai + if (j < 0) { + throw ERROR_INVALID_TICK_COUNT.create(j); + } else { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 13c9cddf7ac0af16676050e3bcdf22b7475a0387..a444c8c57a2ab16eba45b0379841a69ff60a5586 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2786,7 +2786,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 21.0 ) ? "*" : "") + Math.min(Math.round(tps * 100.0) / 100.0, 20.0); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ return (( tps > 21.0 ) ? "*" : "") + Math.min(carpetfixes.helpers.FastMath.round(tps * 100.0) / 100.0, 20.0); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise // Mirai + } + // Paper end + } +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index ec587cf6592a1dc0d90d6f54af1bdfab97aec7c6..0afd56a8b27fce044f7d43b1e4f86b617c0b827f 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -792,7 +792,7 @@ public class Mth { + } + + public static double length(double a, double b) { +- return Math.sqrt(lengthSquared(a, b)); ++ return carpetfixes.helpers.FastMath.hypot(a, b); // Mirai + } + + public static double lengthSquared(double a, double b, double c) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 9d824c56914292810091b358ff7d718add617f21..4f3cce05807715b978792ffa28f2d63315818f54 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1532,7 +1532,7 @@ public abstract class LivingEntity extends Entity { + if (this instanceof ServerPlayer) { + CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, source, f1, amount, flag); + if (f2 > 0.0F && f2 < 3.4028235E37F) { +- ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f2 * 10.0F)); ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, carpetfixes.helpers.FastMath.round(f2 * 10.0F)); // Mirai + } + } + +@@ -2100,9 +2100,9 @@ public abstract class LivingEntity extends Entity { + + if (f3 > 0.0F && f3 < 3.4028235E37F) { + if (this instanceof ServerPlayer) { +- ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, carpetfixes.helpers.FastMath.round(f3 * 10.0F)); // Mirai + } else if (source.getEntity() instanceof ServerPlayer) { +- ((ServerPlayer) source.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ ((ServerPlayer) source.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, carpetfixes.helpers.FastMath.round(f3 * 10.0F)); // Mirai + } + } + } +@@ -2214,9 +2214,9 @@ public abstract class LivingEntity extends Entity { + float f3 = (float) -event.getDamage(DamageModifier.RESISTANCE); + if (f3 > 0.0F && f3 < 3.4028235E37F) { + if (this instanceof ServerPlayer) { +- ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, carpetfixes.helpers.FastMath.round(f3 * 10.0F)); // Mirai + } else if (damagesource.getEntity() instanceof ServerPlayer) { +- ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, carpetfixes.helpers.FastMath.round(f3 * 10.0F)); // Mirai + } + } + } +@@ -2248,10 +2248,10 @@ public abstract class LivingEntity extends Entity { + float f2 = absorptionModifier; + + if (f2 > 0.0F && f2 < 3.4028235E37F && this instanceof net.minecraft.world.entity.player.Player) { +- ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_ABSORBED, carpetfixes.helpers.FastMath.round(f2 * 10.0F)); // Mirai + } + if (f2 > 0.0F && f2 < 3.4028235E37F && damagesource.getEntity() instanceof ServerPlayer) { +- ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); ++ ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_ABSORBED, carpetfixes.helpers.FastMath.round(f2 * 10.0F)); // Mirai + } + + // Purpur start +@@ -2273,7 +2273,7 @@ public abstract class LivingEntity extends Entity { + // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. + ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent + if (f < 3.4028235E37F) { +- ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, carpetfixes.helpers.FastMath.round(f * 10.0F)); // Mirai + } + } + // CraftBukkit end +@@ -2295,7 +2295,7 @@ public abstract class LivingEntity extends Entity { + CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); + f2 = (float) -event.getDamage(DamageModifier.BLOCKING); + if (f2 > 0.0F && f2 < 3.4028235E37F) { +- ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, carpetfixes.helpers.FastMath.round(originalDamage * 10.0F)); // Mirai + } + } + +@@ -3100,13 +3100,13 @@ public abstract class LivingEntity extends Entity { + //this.level.getProfiler().push("rangeChecks"); // Purpur + + // Paper start - stop large pitch and yaw changes from crashing the server +- this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F; ++ this.yRotO += carpetfixes.helpers.FastMath.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F; // Mirai + +- this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F; ++ this.yBodyRotO += carpetfixes.helpers.FastMath.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F; // Mirai + +- this.xRotO += Math.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F; ++ this.xRotO += carpetfixes.helpers.FastMath.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F; // Mirai + +- this.yHeadRotO += Math.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F; ++ this.yHeadRotO += carpetfixes.helpers.FastMath.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F; // Mirai + // Paper end + + //this.level.getProfiler().pop(); // Purpur +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 97668eee40bff129c0a983a6596d0415ddb97b4b..5a17c5df95390120bdd36c86dcd14a334f3a7030 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1128,7 +1128,7 @@ public abstract class Player extends LivingEntity { + float f2 = f1 - f; + + if (f2 > 0.0F && f2 < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ this.awardStat(Stats.DAMAGE_ABSORBED, carpetfixes.helpers.FastMath.round(f2 * 10.0F)); // Mirai + } + + if (f != 0.0F) { +@@ -1138,7 +1138,7 @@ public abstract class Player extends LivingEntity { + this.setHealth(this.getHealth() - f); + this.getCombatTracker().recordDamage(damagesource, f3, f); + if (f < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ this.awardStat(Stats.DAMAGE_TAKEN, carpetfixes.helpers.FastMath.round(f * 10.0F)); // Mirai + } + + } +@@ -1464,7 +1464,7 @@ public abstract class Player extends LivingEntity { + if (target instanceof LivingEntity) { + float f5 = f3 - ((LivingEntity) target).getHealth(); + +- this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F)); ++ this.awardStat(Stats.DAMAGE_DEALT, carpetfixes.helpers.FastMath.round(f5 * 10.0F)); // Mirai + if (j > 0) { + // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item + EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4); +@@ -1737,29 +1737,29 @@ public abstract class Player extends LivingEntity { + int i; + + if (this.isSwimming()) { +- i = Math.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); // Mirai + if (i > 0) { + this.awardStat(Stats.SWIM_ONE_CM, i); + this.causeFoodExhaustion(level.spigotConfig.swimMultiplier * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent // Spigot + } + } else if (this.isEyeInFluid(FluidTags.WATER)) { +- i = Math.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); // Mirai + if (i > 0) { + this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, i); + this.causeFoodExhaustion(level.spigotConfig.swimMultiplier * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent // Spigot + } + } else if (this.isInWater()) { +- i = Math.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); // Mirai + if (i > 0) { + this.awardStat(Stats.WALK_ON_WATER_ONE_CM, i); + this.causeFoodExhaustion(level.spigotConfig.swimMultiplier * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent // Spigot + } + } else if (this.onClimbable()) { + if (dy > 0.0D) { +- this.awardStat(Stats.CLIMB_ONE_CM, (int) Math.round(dy * 100.0D)); ++ this.awardStat(Stats.CLIMB_ONE_CM, (int) carpetfixes.helpers.FastMath.round(dy * 100.0D)); // Mirai + } + } else if (this.onGround) { +- i = Math.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); // Mirai + if (i > 0) { + if (this.isSprinting()) { + this.awardStat(Stats.SPRINT_ONE_CM, i); +@@ -1773,10 +1773,10 @@ public abstract class Player extends LivingEntity { + } + } + } else if (this.isFallFlying()) { +- i = Math.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); // Mirai + this.awardStat(Stats.AVIATE_ONE_CM, i); + } else { +- i = Math.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); ++ i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dz * dz) * 100.0F); // Mirai + if (i > 25) { + this.awardStat(Stats.FLY_ONE_CM, i); + } +@@ -1787,7 +1787,7 @@ public abstract class Player extends LivingEntity { + + public void checkRidingStatistics(double dx, double dy, double dz) { + if (this.isPassenger()) { +- int i = Math.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); ++ int i = carpetfixes.helpers.FastMath.round((float) Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F); // Mirai + + if (i > 0) { + Entity entity = this.getVehicle(); +@@ -1814,7 +1814,7 @@ public abstract class Player extends LivingEntity { + return false; + } else { + if (fallDistance >= 2.0F) { +- this.awardStat(Stats.FALL_ONE_CM, (int) Math.round((double) fallDistance * 100.0D)); ++ this.awardStat(Stats.FALL_ONE_CM, (int) carpetfixes.helpers.FastMath.round((double) fallDistance * 100.0D)); // Mirai + } + + return super.causeFallDamage(fallDistance, damageMultiplier, damageSource); +diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java +index 8b250dab8f3cb788ae1cfad43737afda31b72c0f..7e57163c82f7a4f9df0774f049f724c9b201e023 100644 +--- a/src/main/java/net/minecraft/world/item/Item.java ++++ b/src/main/java/net/minecraft/world/item/Item.java +@@ -166,7 +166,7 @@ public class Item implements ItemLike { + } + + public int getBarWidth(ItemStack stack) { +- return Math.round(13.0F - (float)stack.getDamageValue() * 13.0F / (float)this.maxDamage); ++ return carpetfixes.helpers.FastMath.round(13.0F - (float)stack.getDamageValue() * 13.0F / (float)this.maxDamage); // Mirai + } + + public int getBarColor(ItemStack stack) { +diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +index 1d79da7f8405f7dff3b2e10022a564a9cf2609eb..1d697e31e4bf5a94341f8044b8d580da019e94d7 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +@@ -369,7 +369,7 @@ public class EnchantmentHelper { + } else { + level += 1 + random.nextInt(i / 4 + 1) + random.nextInt(i / 4 + 1); + float f = (random.nextFloat() + random.nextFloat() - 1.0F) * 0.15F; +- level = Mth.clamp(Math.round((float)level + (float)level * f), 1, Integer.MAX_VALUE); ++ level = Mth.clamp(carpetfixes.helpers.FastMath.round((float)level + (float)level * f), 1, Integer.MAX_VALUE); // Mirai + List list2 = getAvailableEnchantmentResults(level, stack, treasureAllowed); + if (!list2.isEmpty()) { + WeightedRandom.getRandomItem(random, list2).ifPresent(list::add); +diff --git a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java +index 16504b8be08064e61b013fa943f692816612cbd0..38f6759501dcc2a0adb9608a9f639c2411acf277 100644 +--- a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -62,7 +62,7 @@ public class DaylightDetectorBlock extends BaseEntityBlock { + float f1 = f < 3.1415927F ? 0.0F : 6.2831855F; + + f += (f1 - f) * 0.2F; +- i = Math.round((float) i * Mth.cos(f)); ++ i = carpetfixes.helpers.FastMath.round((float) i * Mth.cos(f)); // Mirai + } + + i = Mth.clamp(i, (int) 0, (int) 15); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +index 52264a583e79cc6adb9967aebac7f6b3ac129017..f642b7c58b8e9189d9734bf6a699848f9610b66d 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -254,8 +254,8 @@ public abstract class ChunkGenerator { + + for (int j1 = 0; j1 < j; ++j1) { + double d1 = (double) (4 * i + i * i1 * 6) + (randomsource.nextDouble() - 0.5D) * (double) i * 2.5D; +- int k1 = (int) Math.round(Math.cos(d0) * d1); +- int l1 = (int) Math.round(Math.sin(d0) * d1); ++ int k1 = (int) carpetfixes.helpers.FastMath.round(Math.cos(d0) * d1); // Mirai ++ int l1 = (int) carpetfixes.helpers.FastMath.round(Math.sin(d0) * d1); // Mirai + BiomeSource worldchunkmanager = this.biomeSource; + int i2 = SectionPos.sectionToBlockCoord(k1, 8); + int j2 = SectionPos.sectionToBlockCoord(l1, 8); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/SurfaceSystem.java b/src/main/java/net/minecraft/world/level/levelgen/SurfaceSystem.java +index b20ba0b10b5b1682bb5435d9d0bbe4aad25e8062..22a23580ccd861d14031f46b72f309cca6584d3b 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/SurfaceSystem.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/SurfaceSystem.java +@@ -300,7 +300,7 @@ public class SurfaceSystem { + } + + protected BlockState getBand(int x, int y, int z) { +- int i = (int)Math.round(this.clayBandsOffsetNoise.getValue((double)x, 0.0D, (double)z) * 4.0D); ++ int i = (int)carpetfixes.helpers.FastMath.round(this.clayBandsOffsetNoise.getValue((double)x, 0.0D, (double)z) * 4.0D); // Mirai + return this.clayBands[(y + i + this.clayBands.length) % this.clayBands.length]; + } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/ScatteredOreFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/ScatteredOreFeature.java +index 06f27fc8eda9ec160c54759ec95fdade19876d29..567d653469c964922dc5662e48c45dc289222bc2 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/ScatteredOreFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/ScatteredOreFeature.java +@@ -46,6 +46,6 @@ public class ScatteredOreFeature extends Feature { + } + + private int getRandomPlacementInOneAxisRelativeToOrigin(RandomSource randomSource, int spread) { +- return Math.round((randomSource.nextFloat() - randomSource.nextFloat()) * (float)spread); ++ return carpetfixes.helpers.FastMath.round((randomSource.nextFloat() - randomSource.nextFloat()) * (float)spread); // Mirai + } + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +index 15d8e9261a89da30529ac347462c520920ca4e7d..477003d735548ef2f8152681a31fef3354e1f949 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +@@ -68,7 +68,7 @@ public class LootingEnchantFunction extends LootItemConditionalFunction { + + float f = (float) i * this.value.getFloat(context); + +- stack.grow(Math.round(f)); ++ stack.grow(carpetfixes.helpers.FastMath.round(f)); // Mirai + if (this.hasLimit() && stack.getCount() > this.limit) { + stack.setCount(this.limit); + } +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/providers/number/NumberProvider.java b/src/main/java/net/minecraft/world/level/storage/loot/providers/number/NumberProvider.java +index 2a7c75ea447b179ea1ab9db56e8a39d03faa0bce..53ca87c7659a4fff9e99d21217d1ad08c8765836 100644 +--- a/src/main/java/net/minecraft/world/level/storage/loot/providers/number/NumberProvider.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/providers/number/NumberProvider.java +@@ -7,7 +7,7 @@ public interface NumberProvider extends LootContextUser { + float getFloat(LootContext context); + + default int getInt(LootContext context) { +- return Math.round(this.getFloat(context)); ++ return carpetfixes.helpers.FastMath.round(this.getFloat(context)); // Mirai + } + + LootNumberProviderType getType(); +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 731c7dd15f131dc124be6af8f342b122cb89491b..24a82111a5485da1e3903977d0519e9ed502f34d 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -59,8 +59,8 @@ public final class Shapes { + int j = 1 << i; + double d = min * (double)j; + double e = max * (double)j; +- boolean bl = Math.abs(d - (double)Math.round(d)) < 1.0E-7D * (double)j; +- boolean bl2 = Math.abs(e - (double)Math.round(e)) < 1.0E-7D * (double)j; ++ boolean bl = Math.abs(d - (double)carpetfixes.helpers.FastMath.round(d)) < 1.0E-7D * (double)j; // Mirai ++ boolean bl2 = Math.abs(e - (double)carpetfixes.helpers.FastMath.round(e)) < 1.0E-7D * (double)j; // Mirai + if (bl && bl2) { + return i; + } +diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +index 088239d17aa8178cf8af09ec23cfd4deaaf2bbb6..6a02c713c9e5b0a2fb4f8d2a47a62344af12ef95 100644 +--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java ++++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java +@@ -48,6 +48,6 @@ public class TicksPerSecondCommand extends Command + private static String format(double tps) // Paper - Made static + { + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() +- + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise ++ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( carpetfixes.helpers.FastMath.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise // Mirai + } + } diff --git a/patches/server/0011-Fast-speed-check.patch b/patches/server/0011-Fast-speed-check.patch new file mode 100644 index 0000000..813e967 --- /dev/null +++ b/patches/server/0011-Fast-speed-check.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: nostalgic853 +Date: Sat, 22 Oct 2022 09:58:38 +0800 +Subject: [PATCH] Fast speed check + +Original code by NFT-Worlds, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/NFT-Worlds/Server + +This patch was took from Mirai. (https://github.com/etil2jz/Mirai) + +etil2jz's note: +NFT-Worlds is related to Stellar devs, known for countless paid forks mostly taking open source patches, +doing questionable/buggy ones, and claiming breathtaking performance improvements. Never ever pay for +any of those Spigot forks! + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index a727875f6db8d9950d1d9ada67dd39480f3b0da9..c260859b0c8bba464559ad906183301ab62e6590 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1193,7 +1193,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + } + + this.tryCheckInsideBlocks(); +- float f2 = this.getBlockSpeedFactor(); ++ // KeYi start - Fast speed check ++ float f2; ++ if (this.getDeltaMovement().x == 0 && this.getDeltaMovement().z == 0) { ++ f2 = 1; ++ } else { ++ f2 = this.getBlockSpeedFactor(); ++ } ++ // KeYi end + + this.setDeltaMovement(this.getDeltaMovement().multiply((double) f2, 1.0D, (double) f2)); + // Paper start - remove expensive streams from here