fix: fixes #64

This commit is contained in:
Helvetica Volubi
2025-09-28 14:44:04 +08:00
parent 5e658adad3
commit b08756b4b3
21 changed files with 105 additions and 75 deletions
@@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 28 Sep 2025 13:21:30 +0800
Subject: [PATCH] Re-add tick count support
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index b957585cf7cf7f845e20f59c7b355722880f3b4e..9b279d003eb9f780ed2723c98b28d9f4d6e3a281 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -412,6 +412,8 @@ public final class TickRegionScheduler {
}
// Luminol end - Add tick command support
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
+
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
throw new IllegalStateException("Scheduled region should be acquirable");
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index b156b5c635f931a3d4abc0584591f90476d011a6..ef0b401affa58077e8dd32b52063202a1c7e0bb6 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -305,6 +305,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - regionised ticking
public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer();
+ private int tickCount; // Lophine - reuse tick count
+ private int lastTickCount;
@Override
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
@@ -2227,9 +2229,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false;
}
+ // Lophine start - reuse tick count
public int getTickCount() {
- throw new UnsupportedOperationException(); // Folia - region threading
+ return tickCount;
+ }
+
+ public boolean checkTickCount(int period) {
+ if (tickCount % period == 0) {
+ return true;
+ }
+
+ int nextPeriodTick = ((lastTickCount / period) + 1) * period;
+ return nextPeriodTick < tickCount;
+ }
+
+ public void handleTickCount(int tickCount) {
+ this.lastTickCount = this.tickCount;
+ this.tickCount += tickCount;
}
+ // Lophine end - reuse tick count
public int getSpawnProtectionRadius() {
return 16;
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 8405157ec35a443e238fa6866772c839621d73d7..4edb6e6e6287f232f7eef45c747554264ec05319 100644
index c39a114c2f5dfef15e18478281106e6abc4fef42..71a26b3a47a7c5798bf2d2902313b74fefa1cfb8 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -334,6 +334,8 @@ public final class RegionizedServer {
@@ -333,6 +333,8 @@ public final class RegionizedServer {
}
// Luminol end - Add a config to enable tick command
@@ -20,15 +20,6 @@ index 8405157ec35a443e238fa6866772c839621d73d7..4edb6e6e6287f232f7eef45c74755426
// tick connections
this.tickConnections();
@@ -443,6 +445,8 @@ public final class RegionizedServer {
world.updateTickData();
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
+
world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); // required to eventually process ticket updates
}
diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644
--- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
@@ -57,36 +48,6 @@ index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f93
}
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index b156b5c635f931a3d4abc0584591f90476d011a6..0b7c014114f1f8648824fe7c9b75fde3ea79162a 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - regionised ticking
public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer();
+ private int tickCount;
@Override
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
@@ -2227,9 +2228,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false;
}
+ // Lophine start - reuse tick count
public int getTickCount() {
- throw new UnsupportedOperationException(); // Folia - region threading
+ if (false) throw new UnsupportedOperationException(); // Folia - region threading
+ return this.tickCount;
+ }
+
+ public void handleTickCount(int tickCount1) {
+ tickCount = tickCount1;
}
+ // Lophine end - reuse tick count
public int getSpawnProtectionRadius() {
return 16;
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3ddc776bf9e 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -33,10 +33,10 @@ index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4
private DisconnectionDetails disconnectionDetails;
private boolean encrypted;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 0b7c014114f1f8648824fe7c9b75fde3ea79162a..384b121df8bfc72b21b607e8fa4ae90efcc6f3e8 100644
index ef0b401affa58077e8dd32b52063202a1c7e0bb6..ffbbbe5752a0aa0228c1f74f5ac147578805fafa 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -348,6 +348,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -349,6 +349,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Folia end - regionised ticking
@@ -45,7 +45,7 @@ index 0b7c014114f1f8648824fe7c9b75fde3ea79162a..384b121df8bfc72b21b607e8fa4ae90e
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
AtomicReference<S> atomicReference = new AtomicReference<>();
@@ -1039,6 +1041,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1040,6 +1042,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia end - region threading
public void stopServer() {
@@ -53,7 +53,7 @@ index 0b7c014114f1f8648824fe7c9b75fde3ea79162a..384b121df8bfc72b21b607e8fa4ae90e
// Folia start - region threading
// halt scheduler
// don't wait, we may be on a scheduler thread
@@ -1589,7 +1592,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1590,7 +1593,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = this.pauseWhileEmptySeconds() * 20;
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
@@ -62,7 +62,7 @@ index 0b7c014114f1f8648824fe7c9b75fde3ea79162a..384b121df8bfc72b21b607e8fa4ae90e
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1913,6 +1916,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1914,6 +1917,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void tickConnection() {
this.getConnection().tick();
@@ -70,7 +70,7 @@ index 0b7c014114f1f8648824fe7c9b75fde3ea79162a..384b121df8bfc72b21b607e8fa4ae90e
}
private void synchronizeTime(ServerLevel level) {
@@ -2991,6 +2995,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -3001,6 +3005,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return 0;
}
@@ -9,46 +9,56 @@ import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "survux-protocol")
public class SurvuxProtocolConfig implements IConfigModule {
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "servux-protocol")
public class ServuxProtocolConfig implements IConfigModule {
@TransformedConfig(name = "entity-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "entity-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "entity-protocol")
@ConfigInfo(name = "entity-protocol", directory = {"data"})
public static boolean entityProtocol = false;
@TransformedConfig(name = "hud-logger-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-logger-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-logger-protocol")
public static boolean hudLoggerProtocol = false;
@TransformedConfig(name = "hud-metadata-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-protocol")
public static boolean hudMetadataProtocol = false;
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-share-seed")
public static boolean hudMetadataShareSeed = false;
@TransformedConfig(name = "structure-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "structure-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "structure-protocol")
public static boolean structureProtocol = false;
@TransformedConfig(name = "hud-enabled-loggers", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-enabled-loggers", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-enabled-loggers")
public static List<String> hudEnabledLoggers = List.of("tps", "mob_caps");
@TransformedConfig(name = "hud-update-interval", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-update-interval", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-update-interval")
public static int hudUpdateInterval = 1;
@TransformedConfig(name = "litematics-enabled", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-enabled", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "litematics-enabled")
@ConfigInfo(name = "litematics-enabled", directory = {"litematics"})
public static boolean litematicsEnabled = false;
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"misc", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "2097152"})
@ConfigInfo(name = "litematics-max-nbt-size")
@ConfigInfo(name = "litematics-max-nbt-size", directory = {"litematics"})
public static int litematicsMaxNbtSize = 2097152;
@TransformedConfig(name = "litematics-print-max-delay-ticks", directory = {"function", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "1200"})
@ConfigInfo(name = "litematics-print-max-delay-ticks", comments = "The max delay ticks for printing litematics, -1 to disable")
@ConfigInfo(name = "litematics-print-max-delay-ticks", directory = {"litematics"}, comments = "The max delay ticks for printing litematics, -1 to disable")
public static int maxDelay = 1200;
}
@@ -154,7 +154,7 @@ public class ServerBot extends ServerPlayer {
this.notSleepTicks++;
}
if (FakeplayerConfig.regenAmount > 0.0 && getServer().getTickCount() % 20 == 0) {
if (FakeplayerConfig.regenAmount > 0.0 && getServer().checkTickCount(20)) {
float regenAmount = (float) (FakeplayerConfig.regenAmount * 20);
this.setHealth(Math.min(this.getHealth() + regenAmount, this.getMaxHealth()));
}
@@ -18,7 +18,7 @@
package org.leavesmc.leaves.protocol.servux;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.SurvuxProtocolConfig;
import fun.bm.lophine.config.modules.function.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
@@ -144,7 +144,7 @@ public class ServuxEntityDataProtocol implements LeavesProtocol {
@Override
public boolean isActive() {
return SurvuxProtocolConfig.entityProtocol;
return ServuxProtocolConfig.entityProtocol;
}
public enum EntityDataPayloadType {
@@ -20,7 +20,7 @@ package org.leavesmc.leaves.protocol.servux;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.mojang.serialization.DataResult;
import fun.bm.lophine.config.modules.function.SurvuxProtocolConfig;
import fun.bm.lophine.config.modules.function.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
@@ -104,7 +104,7 @@ public class ServuxHudDataProtocol implements LeavesProtocol {
metadata.putString("id", HudDataPayload.CHANNEL.toString());
metadata.putInt("version", PROTOCOL_VERSION);
metadata.putString("servux", ServuxProtocol.SERVUX_STRING);
if (SurvuxProtocolConfig.hudLoggerProtocol) {
if (ServuxProtocolConfig.hudLoggerProtocol) {
CompoundTag nbt = new CompoundTag();
for (DataLogger.Type type : DataLogger.Type.VALUES) {
nbt.putBoolean(type.getSerializedName(), isLoggerTypeEnabled(type));
@@ -185,7 +185,7 @@ public class ServuxHudDataProtocol implements LeavesProtocol {
metadata.putInt("spawnPosZ", spawnPos.getZ());
metadata.putInt("spawnChunkRadius", level.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS));
if (SurvuxProtocolConfig.hudMetadataShareSeed) {
if (ServuxProtocolConfig.hudMetadataShareSeed) {
metadata.putLong("worldSeed", level.getSeed());
}
}
@@ -217,7 +217,7 @@ public class ServuxHudDataProtocol implements LeavesProtocol {
}
private static boolean isLoggerTypeEnabled(DataLogger.Type type) {
return SurvuxProtocolConfig.hudEnabledLoggers.contains(type.getSerializedName());
return ServuxProtocolConfig.hudEnabledLoggers.contains(type.getSerializedName());
}
@ProtocolHandler.Ticker
@@ -233,13 +233,13 @@ public class ServuxHudDataProtocol implements LeavesProtocol {
@ProtocolHandler.Ticker(tickerId = "logger")
public void loggerTick() {
if (!SurvuxProtocolConfig.hudLoggerProtocol) {
if (!ServuxProtocolConfig.hudLoggerProtocol) {
return;
}
MinecraftServer server = MinecraftServer.getServer();
if (server.getTickCount() % SurvuxProtocolConfig.hudUpdateInterval == 0) {
if (server.checkTickCount(ServuxProtocolConfig.hudUpdateInterval)) {
LOGGERS.forEach((type, logger) -> {
if (!isLoggerTypeEnabled(type)) {
return;
@@ -277,7 +277,7 @@ public class ServuxHudDataProtocol implements LeavesProtocol {
@Override
public boolean isActive() {
return SurvuxProtocolConfig.hudMetadataProtocol;
return ServuxProtocolConfig.hudMetadataProtocol;
}
@Override
@@ -18,7 +18,7 @@
package org.leavesmc.leaves.protocol.servux;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.SurvuxProtocolConfig;
import fun.bm.lophine.config.modules.function.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
@@ -57,7 +57,6 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
public static final int PROTOCOL_VERSION = 2;
private static final int updateInterval = 40;
private static final int timeout = 30 * 20;
private static final Map<Integer, ServerPlayer> players = new ConcurrentHashMap<>();
private static final Map<UUID, Map<ChunkPos, Timeout>> timeouts = new HashMap<>();
private static int retainDistance;
@@ -105,7 +104,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
if (chunkHasStructureReferences(pos.x, pos.z, chunk.getLevel())) {
final Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new HashMap<>());
map.computeIfAbsent(pos, (p) -> new Timeout(tickCounter - timeout));
map.computeIfAbsent(pos, (p) -> new Timeout(tickCounter - ServuxProtocolConfig.maxDelay));
}
}
@@ -145,7 +144,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
tag.putString("id", StructuresPayload.CHANNEL.toString());
tag.putInt("version", PROTOCOL_VERSION);
tag.putString("servux", ServuxProtocol.SERVUX_STRING);
tag.putInt("timeout", timeout);
tag.putInt("timeout", ServuxProtocolConfig.maxDelay);
sendPacket(player, new StructuresPayload(StructuresPayloadType.PACKET_S2C_METADATA, tag));
}
@@ -270,7 +269,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
for (Map.Entry<ChunkPos, Timeout> entry : map.entrySet()) {
Timeout out = entry.getValue();
if (out.needsUpdate(tickCounter, timeout)) {
if (out.needsUpdate(ServuxProtocolConfig.maxDelay, tickCounter)) {
positionsToUpdate.add(entry.getKey());
}
}
@@ -336,7 +335,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
@Override
public boolean isActive() {
return SurvuxProtocolConfig.structureProtocol;
return ServuxProtocolConfig.structureProtocol;
}
public enum StructuresPayloadType {
@@ -410,7 +409,8 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
}
public boolean needsUpdate(int currentTick, int timeout) {
return currentTick - this.lastSync >= timeout;
if (timeout == -1 || currentTick - this.lastSync >= timeout) return true;
return MinecraftServer.getServer().checkTickCount(timeout);
}
public void setLastSync(int tickCounter) {
@@ -17,7 +17,7 @@
package org.leavesmc.leaves.protocol.servux.litematics;
import fun.bm.lophine.config.modules.function.SurvuxProtocolConfig;
import fun.bm.lophine.config.modules.function.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -133,7 +133,7 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
}
playerSession.remove(uuid);
fullPacket.readVarInt();
Tag tag = FriendlyByteBuf.readNbt(fullPacket, new NbtAccounter(SurvuxProtocolConfig.litematicsMaxNbtSize == -1 ? Long.MAX_VALUE : SurvuxProtocolConfig.litematicsMaxNbtSize, 512));
Tag tag = FriendlyByteBuf.readNbt(fullPacket, new NbtAccounter(ServuxProtocolConfig.litematicsMaxNbtSize == -1 ? Long.MAX_VALUE : ServuxProtocolConfig.litematicsMaxNbtSize, 512));
if (!(tag instanceof CompoundTag)) {
ServuxProtocol.LOGGER.error("cannot read nbt tag from packet");
return;
@@ -275,7 +275,7 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
@Override
public boolean isActive() {
return SurvuxProtocolConfig.litematicsEnabled;
return ServuxProtocolConfig.litematicsEnabled;
}
public enum ServuxLitematicaPayloadType {
@@ -18,7 +18,7 @@
package org.leavesmc.leaves.protocol.servux.litematics.placement;
import com.google.common.collect.ImmutableMap;
import fun.bm.lophine.config.modules.function.SurvuxProtocolConfig;
import fun.bm.lophine.config.modules.function.ServuxProtocolConfig;
import io.papermc.paper.threadedregions.RegionizedServer;
import me.earthme.luminol.utils.NullPlugin;
import net.kyori.adventure.text.Component;
@@ -316,7 +316,7 @@ public class SchematicPlacement {
);
final NullPlugin nullPlugin = new NullPlugin();
scheduleTask(nullPlugin, serverWorld, count, count_full, player, timeStart, SurvuxProtocolConfig.maxDelay);
scheduleTask(nullPlugin, serverWorld, count, count_full, player, timeStart, ServuxProtocolConfig.maxDelay);
}
private void scheduleTask(Plugin plugin, ServerLevel serverWorld, AtomicInteger count1, AtomicInteger count2, ServerPlayer player, long timeStart, int retryCount) {