diff --git a/patches/server/0963-Tick-freeze.patch b/patches/server/0963-Tick-freeze.patch new file mode 100644 index 0000000000..bb73312bd0 --- /dev/null +++ b/patches/server/0963-Tick-freeze.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lixfel +Date: Thu, 13 Apr 2023 10:28:53 +0200 +Subject: [PATCH] Tick freeze + + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 54c2b7fba83d6f06dba95b1bb5b487a02048d6e6..cc51b2b9188d798eb51fdc3bfb87f02bb9095204 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -625,6 +625,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + } + + public void tick(BooleanSupplier shouldKeepTicking) { ++ if(!freezed) { + // Paper start - optimise checkDespawn + this.playersAffectingSpawning.clear(); + for (ServerPlayer player : this.players) { +@@ -633,9 +634,11 @@ public class ServerLevel extends Level implements WorldGenLevel { + } + } + // Paper end - optimise checkDespawn ++ } // freezed + ProfilerFiller gameprofilerfiller = this.getProfiler(); + + this.handlingTick = true; ++ if(!freezed) { + gameprofilerfiller.push("world border"); + this.getWorldBorder().tick(); + gameprofilerfiller.popPush("weather"); +@@ -681,14 +684,17 @@ public class ServerLevel extends Level implements WorldGenLevel { + this.timings.raids.startTiming(); // Paper - timings + this.raids.tick(); + this.timings.raids.stopTiming(); // Paper - timings ++ } // freezed + gameprofilerfiller.popPush("chunkSource"); + this.timings.chunkProviderTick.startTiming(); // Paper - timings + this.getChunkSource().tick(shouldKeepTicking, true); + this.timings.chunkProviderTick.stopTiming(); // Paper - timings ++ if(!freezed) { + gameprofilerfiller.popPush("blockEvents"); + timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); + timings.doSounds.stopTiming(); // Spigot ++ } // freezed + this.handlingTick = false; + gameprofilerfiller.pop(); + boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players +@@ -697,7 +703,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + this.resetEmptyTime(); + } + +- if (flag || this.emptyTime++ < 300) { ++ if (!freezed && (flag || this.emptyTime++ < 300)) { + gameprofilerfiller.push("entities"); + timings.tickEntities.startTiming(); // Spigot + if (this.dragonFight != null) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 3cbf801b2e5420c0e870f73788deb550e49ad54d..f6d1030725e1ebeeb2d62df401faf781171d5bee 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -181,6 +181,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + ++ public boolean freezed = false; ++ + // Paper start - fix and optimise world upgrading + // copied from below + public static ResourceKey getDimensionKey(DimensionType manager) { diff --git a/patches/server/0963-TickFreeze.patch b/patches/server/0963-TickFreeze.patch deleted file mode 100644 index adf63af4b0..0000000000 --- a/patches/server/0963-TickFreeze.patch +++ /dev/null @@ -1,431 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lixfel -Date: Wed, 1 Feb 2023 21:49:21 +0100 -Subject: [PATCH] TickFreeze - - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 54c2b7fba83d6f06dba95b1bb5b487a02048d6e6..9d2a39fb012cfc8a5b186b389c6089a4d206301b 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1,21 +1,18 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.TimingHistory; - import com.google.common.annotations.VisibleForTesting; --import co.aikar.timings.TimingHistory; // Paper - import com.google.common.collect.Lists; - import com.mojang.datafixers.DataFixer; - import com.mojang.datafixers.util.Pair; - import com.mojang.logging.LogUtils; - import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.ints.IntArrayList; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.longs.LongSets; -+import it.unimi.dsi.fastutil.objects.*; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; --import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; --import it.unimi.dsi.fastutil.objects.ObjectArrayList; --import it.unimi.dsi.fastutil.objects.ObjectIterator; --import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; --import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import java.io.BufferedWriter; - import java.io.IOException; - import java.io.Writer; -@@ -40,28 +37,15 @@ import javax.annotation.Nonnull; - import javax.annotation.Nullable; - import net.minecraft.CrashReport; - import net.minecraft.Util; --import net.minecraft.core.BlockPos; --import net.minecraft.core.Direction; --import net.minecraft.core.Holder; --import net.minecraft.core.HolderSet; --import net.minecraft.core.RegistryAccess; --import net.minecraft.core.SectionPos; -+import net.minecraft.core.*; - import net.minecraft.core.particles.ParticleOptions; - import net.minecraft.core.registries.BuiltInRegistries; - import net.minecraft.core.registries.Registries; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.MutableComponent; - import net.minecraft.network.protocol.Packet; --import net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket; --import net.minecraft.network.protocol.game.ClientboundBlockEventPacket; --import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; --import net.minecraft.network.protocol.game.ClientboundExplodePacket; --import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; --import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; --import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; --import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; --import net.minecraft.network.protocol.game.ClientboundSoundPacket; --import net.minecraft.network.protocol.game.DebugPackets; -+import net.minecraft.network.protocol.game.*; -+import net.minecraft.network.syncher.SynchedEntityData; - import net.minecraft.resources.ResourceKey; - import io.papermc.paper.util.MCUtil; - import net.minecraft.server.MinecraftServer; -@@ -79,13 +63,7 @@ import net.minecraft.util.Unit; - import net.minecraft.util.profiling.ProfilerFiller; - import net.minecraft.world.DifficultyInstance; - import net.minecraft.world.damagesource.DamageSource; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.entity.EntityType; --import net.minecraft.world.entity.LightningBolt; --import net.minecraft.world.entity.LivingEntity; --import net.minecraft.world.entity.Mob; --import net.minecraft.world.entity.MobCategory; --import net.minecraft.world.entity.ReputationEventHandler; -+import net.minecraft.world.entity.*; - import net.minecraft.world.entity.ai.navigation.PathNavigation; - import net.minecraft.world.entity.ai.village.ReputationEventType; - import net.minecraft.world.entity.ai.village.poi.PoiManager; -@@ -96,23 +74,15 @@ import net.minecraft.world.entity.animal.WaterAnimal; - import net.minecraft.world.entity.animal.horse.SkeletonHorse; - import net.minecraft.world.entity.boss.EnderDragonPart; - import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -+import net.minecraft.world.entity.item.ItemEntity; -+import net.minecraft.world.entity.item.PrimedTnt; - import net.minecraft.world.entity.npc.Npc; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.raid.Raid; - import net.minecraft.world.entity.raid.Raids; - import net.minecraft.world.flag.FeatureFlagSet; - import net.minecraft.world.item.crafting.RecipeManager; --import net.minecraft.world.level.BlockEventData; --import net.minecraft.world.level.ChunkPos; --import net.minecraft.world.level.CustomSpawner; --import net.minecraft.world.level.Explosion; --import net.minecraft.world.level.ExplosionDamageCalculator; --import net.minecraft.world.level.ForcedChunksSavedData; --import net.minecraft.world.level.GameRules; --import net.minecraft.world.level.Level; --import net.minecraft.world.level.NaturalSpawner; --import net.minecraft.world.level.StructureManager; --import net.minecraft.world.level.WorldGenLevel; -+import net.minecraft.world.level.*; - import net.minecraft.world.level.biome.Biome; - import net.minecraft.world.level.biome.BiomeSource; - import net.minecraft.world.level.block.Block; -@@ -128,12 +98,7 @@ import net.minecraft.world.level.chunk.storage.EntityStorage; - import net.minecraft.world.level.dimension.BuiltinDimensionTypes; - import net.minecraft.world.level.dimension.LevelStem; - import net.minecraft.world.level.dimension.end.EndDragonFight; --import net.minecraft.world.level.entity.EntityPersistentStorage; --import net.minecraft.world.level.entity.EntityTickList; --import net.minecraft.world.level.entity.EntityTypeTest; --import net.minecraft.world.level.entity.LevelCallback; --import net.minecraft.world.level.entity.LevelEntityGetter; --import net.minecraft.world.level.entity.PersistentEntitySectionManager; -+import net.minecraft.world.level.entity.*; - import net.minecraft.world.level.gameevent.DynamicGameEventListener; - import net.minecraft.world.level.gameevent.GameEvent; - import net.minecraft.world.level.gameevent.GameEventDispatcher; -@@ -174,6 +139,21 @@ import org.bukkit.event.world.TimeSkipEvent; - // CraftBukkit end - import it.unimi.dsi.fastutil.ints.IntArrayList; // Paper - -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.io.BufferedWriter; -+import java.io.IOException; -+import java.io.Writer; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.util.*; -+import java.util.concurrent.Executor; -+import java.util.function.BooleanSupplier; -+import java.util.function.Function; -+import java.util.function.Predicate; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+ - public class ServerLevel extends Level implements WorldGenLevel { - - public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); -@@ -625,6 +605,9 @@ public class ServerLevel extends Level implements WorldGenLevel { - } - - public void tick(BooleanSupplier shouldKeepTicking) { -+ // SteamWar start -+ currentlyFrozen = freezed; -+ // SteamWar end - // Paper start - optimise checkDespawn - this.playersAffectingSpawning.clear(); - for (ServerPlayer player : this.players) { -@@ -664,10 +647,14 @@ public class ServerLevel extends Level implements WorldGenLevel { - } - - this.updateSkyBrightness(); -- this.tickTime(); -+ // SteamWar start -+ if (!currentlyFrozen) { -+ this.tickTime(); -+ } -+ // SteamWar end - gameprofilerfiller.popPush("tickPending"); - timings.scheduledBlocks.startTiming(); // Paper -- if (!this.isDebug()) { -+ if (!currentlyFrozen && !this.isDebug()) { // SteamWar - j = this.getGameTime(); - gameprofilerfiller.push("blockTicks"); - this.blockTicks.tick(j, 65536, this::tickBlock); -@@ -687,7 +674,11 @@ public class ServerLevel extends Level implements WorldGenLevel { - this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.popPush("blockEvents"); - timings.doSounds.startTiming(); // Spigot -- this.runBlockEvents(); -+ // SteamWar start -+ if (!currentlyFrozen) { -+ this.runBlockEvents(); -+ } -+ // SteamWar end - timings.doSounds.stopTiming(); // Spigot - this.handlingTick = false; - gameprofilerfiller.pop(); -@@ -697,6 +688,15 @@ public class ServerLevel extends Level implements WorldGenLevel { - this.resetEmptyTime(); - } - -+ // SteamWar start -+ lastFreezed = false; -+ if (!currentlyFrozen && !physicsTick.isEmpty()) { -+ physicsTick.forEach((blockPos, runnables) -> runnables.forEach(Runnable::run)); -+ physicsTick.clear(); -+ lastFreezed = true; -+ } -+ // SteamWar end -+ - if (flag || this.emptyTime++ < 300) { - gameprofilerfiller.push("entities"); - timings.tickEntities.startTiming(); // Spigot -@@ -728,16 +728,30 @@ public class ServerLevel extends Level implements WorldGenLevel { - } - - gameprofilerfiller.push("tick"); -- this.guardEntityTick(this::tickNonPassenger, entity); -+ // SteamWar start -+ if (!currentlyFrozen || entity instanceof Player) { -+ this.guardEntityTick(this::tickNonPassenger, entity); -+ } -+ // SteamWar end - gameprofilerfiller.pop(); - } - } - } - }); -+ // SteamWar start -+ getEntities().getAll().forEach(entity -> { -+ if (entity instanceof Player || entity instanceof ItemEntity) return; -+ sendEntityPackets(entity); -+ }); -+ // SteamWar end - timings.entityTick.stopTiming(); // Spigot - timings.tickEntities.stopTiming(); // Spigot - gameprofilerfiller.pop(); -- this.tickBlockEntities(); -+ // SteamWar start -+ if (!currentlyFrozen) { -+ this.tickBlockEntities(); -+ } -+ // SteamWar end - } - - gameprofilerfiller.push("entityManagement"); -@@ -797,6 +811,9 @@ public class ServerLevel extends Level implements WorldGenLevel { - // Paper end - - public void tickChunk(LevelChunk chunk, int randomTickSpeed) { -+ // SteamWar start -+ if (currentlyFrozen) return; -+ // SteamWar end - ChunkPos chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.getMinBlockX(); -@@ -1475,8 +1492,55 @@ public class ServerLevel extends Level implements WorldGenLevel { - this.entityLookup.addNewEntity(player); // Paper - rewite chunk system - } - -+ // SteamWar start -+ private boolean sendEntityPackets(Entity entity) { -+ if (currentlyFrozen && !(entity instanceof ItemEntity)) { -+ ClientboundSetEntityMotionPacket packetPlayOutEntityVelocity = new ClientboundSetEntityMotionPacket(entity.getId(), new Vec3(0, 0, 0)); -+ ClientboundTeleportEntityPacket packetPlayOutEntityTeleport = new ClientboundTeleportEntityPacket(entity); -+ if (entity instanceof PrimedTnt) { -+ PrimedTnt entityTNTPrimed = new PrimedTnt(EntityType.TNT, this); -+ entityTNTPrimed.setNoGravity(true); -+ entityTNTPrimed.setPos(entity.getX(), entity.getY(), entity.getZ()); -+ entityTNTPrimed.setFuse(((PrimedTnt) entity).getFuse()); -+ entityTNTPrimed.setFuse(entityTNTPrimed.getFuse() - (entityTNTPrimed.getFuse() % 5 == 1 ? 1 : 0)); -+ } -+ players.forEach(player -> { -+ player.connection.send(packetPlayOutEntityVelocity); -+ player.connection.send(packetPlayOutEntityTeleport); -+ }); -+ -+ List> nonDefaultValues = entity.getEntityData().getNonDefaultValues(); -+ if(nonDefaultValues != null) { -+ ClientboundSetEntityDataPacket packetPlayOutEntityMetadata = new ClientboundSetEntityDataPacket(entity.getId(), nonDefaultValues); -+ players.forEach(player -> player.connection.send(packetPlayOutEntityMetadata)); -+ } -+ return true; -+ } -+ if (lastFreezed && !(entity instanceof ItemEntity)) { -+ ClientboundSetEntityMotionPacket packetPlayOutEntityVelocity = new ClientboundSetEntityMotionPacket(entity); -+ ClientboundTeleportEntityPacket packetPlayOutEntityTeleport = new ClientboundTeleportEntityPacket(entity); -+ -+ players.forEach(player -> { -+ player.connection.send(packetPlayOutEntityVelocity); -+ player.connection.send(packetPlayOutEntityTeleport); -+ }); -+ -+ List> nonDefaultValues = entity.getEntityData().getNonDefaultValues(); -+ if(nonDefaultValues != null) { -+ ClientboundSetEntityDataPacket packetPlayOutEntityMetadata = new ClientboundSetEntityDataPacket(entity.getId(), nonDefaultValues); -+ players.forEach(player -> player.connection.send(packetPlayOutEntityMetadata)); -+ } -+ } -+ return false; -+ } -+ // SteamWar end -+ - // CraftBukkit start - private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { -+ // SteamWar start -+ if (sendEntityPackets(entity)) return true; -+ // SteamWar end -+ - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot - // Paper start - if (entity.valid) { -@@ -1700,12 +1764,24 @@ public class ServerLevel extends Level implements WorldGenLevel { - - @Override - public void updateNeighborsAt(BlockPos pos, Block sourceBlock) { -+ if (currentlyFrozen) { -+ physicsTick.computeIfAbsent(pos, p -> new ArrayList<>()).add(() -> { -+ updateNeighborsAt(pos, sourceBlock); -+ }); -+ return; -+ } - if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null); - } - - @Override - public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block sourceBlock, Direction direction) { -+ if (currentlyFrozen) { -+ physicsTick.computeIfAbsent(pos, p -> new ArrayList<>()).add(() -> { -+ updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction); -+ }); -+ return; -+ } - this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction); - } - -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 3cbf801b2e5420c0e870f73788deb550e49ad54d..5e173f3b96fc03baf53b9a7b8dcc37828fe8f7c7 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -8,9 +8,7 @@ import com.google.common.base.MoreObjects; - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; - import java.io.IOException; --import java.util.Iterator; --import java.util.List; --import java.util.Objects; -+import java.util.*; - import java.util.function.Consumer; - import java.util.function.Predicate; - import java.util.function.Supplier; -@@ -47,6 +45,7 @@ import net.minecraft.world.entity.boss.enderdragon.EnderDragon; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; - import net.minecraft.world.item.crafting.RecipeManager; - import net.minecraft.world.level.biome.Biome; - import net.minecraft.world.level.biome.BiomeManager; -@@ -181,6 +180,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here - -+ // SteamWar start -+ public boolean freezed = false; -+ protected boolean currentlyFrozen = false; -+ protected boolean lastFreezed = false; -+ protected Map> physicsTick = new LinkedHashMap<>(); -+ -+ public boolean getCurrentlyFrozen() { -+ return currentlyFrozen; -+ } -+ -+ public void addPhysicsTick(BlockPos pos, Runnable runnable) { -+ physicsTick.computeIfAbsent(pos, k -> new ArrayList<>()).add(runnable); -+ } -+ // SteamWar end -+ - // Paper start - fix and optimise world upgrading - // copied from below - public static ResourceKey getDimensionKey(DimensionType manager) { -@@ -536,6 +550,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } else { - LevelChunk chunk = this.getChunkAt(pos); - Block block = state.getBlock(); -+ // SteamWar start -+ if (currentlyFrozen && block.asItem().equals(Items.AIR)) { -+ physicsTick.remove(pos); -+ } -+ // SteamWar end - - // CraftBukkit start - capture blockstates - boolean captured = false; -@@ -552,6 +571,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - if (iblockdata1 == null) { - // CraftBukkit start - remove blockstate if failed (or the same) -+ // SteamWar start -+ if (currentlyFrozen) { -+ physicsTick.remove(pos); -+ } -+ // SteamWar end - if (this.captureBlockStates && captured) { - this.capturedBlockStates.remove(pos); - } -@@ -654,8 +678,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - } - // CraftBukkit end -- iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); -- iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); -+ // SteamWar start -+ if (!currentlyFrozen) { -+ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); -+ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); -+ } else { -+ physicsTick.computeIfAbsent(blockposition, __ -> new ArrayList<>()).add(() -> { -+ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); -+ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); -+ }); -+ } -+ // SteamWar end - } - - // CraftBukkit start - SPIGOT-5710 -diff --git a/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java -index 19faa8f5f891c1ffbed0af8391dee8202433c447..84373b6f1558174ebe66cd7ee1d8307f141be7ae 100644 ---- a/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java -+++ b/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java -@@ -51,6 +51,12 @@ public interface NeighborUpdater { - } - - static void executeUpdate(Level world, BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { -+ if (world.getCurrentlyFrozen()) { -+ world.addPhysicsTick(sourcePos, () -> { -+ executeUpdate(world, state, pos, sourceBlock, sourcePos, notify); -+ }); -+ return; -+ } - try { - // CraftBukkit start - CraftWorld cworld = ((ServerLevel) world).getWorld();