Index: src/main/java/net/minecraft/server/WorldServer.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java (revision 571772e5fd38f66c11220ce29cd15d70e8da46f6) +++ b/src/main/java/net/minecraft/server/WorldServer.java (date 1639502280606) @@ -14,38 +14,28 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectIterator; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.Writer; -import java.nio.file.Files; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Queue; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executor; -import java.util.function.BooleanSupplier; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - -// CraftBukkit start -import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.WeatherType; -import org.bukkit.craftbukkit.SpigotTimings; // Spigot import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.server.MapInitializeEvent; import org.bukkit.event.weather.LightningStrikeEvent; import org.bukkit.event.world.TimeSkipEvent; + +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.util.*; +import java.util.concurrent.Executor; +import java.util.function.BooleanSupplier; +import java.util.function.Predicate; +import java.util.logging.Level; +import java.util.stream.Collectors; // CraftBukkit end public class WorldServer extends World { @@ -161,6 +151,7 @@ public void doTick(BooleanSupplier booleansupplier) { GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + currentlyFrozen = freezed; // Do not Change freezed mid tick! this.ticking = true; gameprofilerfiller.enter("world border"); @@ -303,12 +294,14 @@ } this.N(); - this.a(); + if (!currentlyFrozen) { + this.a(); + } gameprofilerfiller.exitEnter("chunkSource"); this.getChunkProvider().tick(booleansupplier); gameprofilerfiller.exitEnter("tickPending"); timings.doTickPending.startTiming(); // Spigot - if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { + if (!currentlyFrozen && this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { this.nextTickListBlock.b(); this.nextTickListFluid.b(); } @@ -322,7 +315,9 @@ gameprofilerfiller.exitEnter("blockEvents"); timings.doSounds.startTiming(); // Spigot - this.ad(); + if (!currentlyFrozen) { + this.ad(); + } timings.doSounds.stopTiming(); // Spigot this.ticking = false; gameprofilerfiller.exitEnter("entities"); @@ -332,19 +327,28 @@ this.resetEmptyTime(); } + lastFreezed = false; + if (!currentlyFrozen && !physicsTick.isEmpty()) { + physicsTick.forEach((blockPosition, list) -> list.forEach(Runnable::run)); + physicsTick.clear(); + lastFreezed = true; + } + if (flag3 || this.emptyTime++ < 300) { timings.tickEntities.startTiming(); // Spigot this.worldProvider.j(); gameprofilerfiller.enter("global"); Entity entity; - for (i = 0; i < this.globalEntityList.size(); ++i) { entity = (Entity) this.globalEntityList.get(i); // CraftBukkit start - Fixed an NPE if (entity == null) { continue; } + if (currentlyFrozen && !(entity instanceof EntityPlayer)) { + continue; + } // CraftBukkit end this.a((entity1) -> { ++entity1.ticksLived; @@ -415,7 +419,9 @@ gameprofilerfiller.exit(); timings.tickEntities.stopTiming(); // Spigot - this.tickBlockEntities(); + if (!currentlyFrozen) { + this.tickBlockEntities(); + } } gameprofilerfiller.exit(); @@ -428,6 +434,7 @@ } public void a(Chunk chunk, int i) { + if (currentlyFrozen) return; ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.d(); @@ -602,6 +609,36 @@ } public void entityJoinedWorld(Entity entity) { + if (currentlyFrozen && !(entity instanceof EntityPlayer) && !(entity instanceof EntityItem)) { + PacketPlayOutEntityVelocity packetPlayOutEntityVelocity = new PacketPlayOutEntityVelocity(entity.getId(), new Vec3D(0, 0, 0)); + PacketPlayOutEntityTeleport packetPlayOutEntityTeleport = new PacketPlayOutEntityTeleport(entity); + PacketPlayOutEntityMetadata packetPlayOutEntityMetadata; + if (entity instanceof EntityTNTPrimed) { + EntityTNTPrimed entityTNTPrimed = new EntityTNTPrimed(EntityTypes.TNT, this); + entityTNTPrimed.setNoGravity(true); + entityTNTPrimed.setPosition(entity.locX(), entity.locY(), entity.locZ()); + entityTNTPrimed.setFuseTicks(((EntityTNTPrimed) entity).getFuseTicks()); + packetPlayOutEntityMetadata = new PacketPlayOutEntityMetadata(entity.getId(), entityTNTPrimed.getDataWatcher(), true); + } else { + packetPlayOutEntityMetadata = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); + } + players.forEach(entityPlayer -> { + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityVelocity); + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityTeleport); + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityMetadata); + }); + return; + } + if (lastFreezed && !(entity instanceof EntityPlayer) && !(entity instanceof EntityItem)) { + PacketPlayOutEntityVelocity packetPlayOutEntityVelocity = new PacketPlayOutEntityVelocity(entity); + PacketPlayOutEntityTeleport packetPlayOutEntityTeleport = new PacketPlayOutEntityTeleport(entity); + PacketPlayOutEntityMetadata packetPlayOutEntityMetadata = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); + players.forEach(entityPlayer -> { + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityVelocity); + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityTeleport); + entityPlayer.playerConnection.sendPacket(packetPlayOutEntityMetadata); + }); + } if (entity instanceof EntityHuman || this.getChunkProvider().a(entity)) { // Spigot start if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { Index: src/main/java/net/minecraft/server/World.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java (revision 571772e5fd38f66c11220ce29cd15d70e8da46f6) +++ b/src/main/java/net/minecraft/server/World.java (date 1639502482332) @@ -1,29 +1,23 @@ package net.minecraft.server; import com.google.common.collect.Lists; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Predicate; -import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.util.Supplier; - -// CraftBukkit start -import java.util.HashMap; -import java.util.Map; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.SpigotTimings; // Spigot import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.SpigotTimings; import org.bukkit.craftbukkit.block.CapturedBlockState; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Predicate; // CraftBukkit end public abstract class World implements GeneratorAccess, AutoCloseable { @@ -76,6 +70,11 @@ private org.spigotmc.TickLimiter tileLimiter; private int tileTickPosition; + public boolean freezed = false; + protected boolean currentlyFrozen = false; + protected boolean lastFreezed = false; + protected Map> physicsTick = new LinkedHashMap<>(); + public CraftWorld getWorld() { return this.world; } @@ -211,6 +210,9 @@ } else { Chunk chunk = this.getChunkAtWorldCoords(blockposition); Block block = iblockdata.getBlock(); + if (block.g().key.equals("minecraft:air")) { + physicsTick.remove(blockposition); + } // CraftBukkit start - capture blockstates boolean captured = false; @@ -225,6 +227,7 @@ if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) + physicsTick.remove(blockposition); if (this.captureBlockStates && captured) { this.capturedBlockStates.remove(blockposition); } @@ -322,8 +325,15 @@ } } // CraftBukkit end - iblockdata.a(this, blockposition, j); - iblockdata.b(this, blockposition, j); + if (!currentlyFrozen) { + iblockdata.a(this, blockposition, j); + iblockdata.b(this, blockposition, j); + } else { + physicsTick.computeIfAbsent(blockposition, (k) -> new ArrayList<>()).add(() -> { + iblockdata.a(this, blockposition, j); + iblockdata.b(this, blockposition, j); + }); + } } this.a(blockposition, iblockdata1, iblockdata2); @@ -418,6 +428,12 @@ } public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) { + if (currentlyFrozen) { + physicsTick.computeIfAbsent(blockposition, (k) -> new ArrayList<>()).add(() -> { + this.a(blockposition, block, blockposition1); + }); + return; + } if (!this.isClientSide) { IBlockData iblockdata = this.getType(blockposition); @@ -1226,6 +1242,14 @@ } public void playBlockAction(BlockPosition blockposition, Block block, int i, int j) { + /* + if (!currentlyFrozen) { + physicsTick.put(blockposition, () -> { + this.getType(blockposition).a(this, blockposition, i, j); + }); + return; + } + */ this.getType(blockposition).a(this, blockposition, i, j); }