Files
Shiroha/shiroha-server/minecraft-patches/features/0053-Add-status-bar.patch
T
NanaChiyo0721 1bb895c165
Shiroha CI / build (push) Canceled after 0s
Shiroha CI / Event File (push) Canceled after 0s
Fix incorrect ticket lock size computing
Yeah this would fully solve the issue of chunk unloading race condition

The same fix was already initially added at "Force clamp grid-exponent to 1~6"
2026-08-09 14:57:32 +08:00

349 lines
18 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Thu, 9 Jul 2026 12:10:04 +0800
Subject: [PATCH] Add status bar
diff --git a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
index 52dcbcf64c3a510d4a4524b7d0ee226d9a73511d..051d601e7e809518e8d82ae4ae3259054d704f51 100644
--- a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
+++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
@@ -122,6 +122,7 @@ public abstract class BaseChunkSystemHooks implements ca.spottedleaf.moonrise.co
@Override
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
+ chunk.getChunkHot().clear(); // KioCG
chunk.getLevel().getCurrentWorldData().removeTickingChunk(chunk); // Folia - region threading
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 170ff99a055d7ea582d6a18ef6acd57269d943c4..c4dddd5c66098301de2abc2de93d4409cd14531d 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1741,7 +1741,46 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia end - region threading
//this.tickCount++; // Folia - region threading
//this.tickRateManager.tick(); // Folia - region threading
+ // KioCG start - ChunkHot
+ final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.level.chunk.LevelChunk> chunks = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>();
+ if (region != null){
+ for (net.minecraft.world.level.chunk.LevelChunk chunk : region.world.getCurrentWorldData().getTickingChunks()) {
+ /* wait for rewrite - temporarily crash fix
+ for (net.minecraft.server.level.ServerChunkCache.ChunkAndHolder chunkAndHolder : region.world.getCurrentWorldData().getTickingChunks()){
+ final net.minecraft.world.level.chunk.LevelChunk chunk = chunkAndHolder.chunk();
+ */
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(region.world, chunk.locX, chunk.locZ)){
+ continue;
+ }
+
+ chunks.add(chunk);
+ }
+ }
+ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
+ final java.util.Iterator<net.minecraft.world.level.chunk.LevelChunk> chunkIterator = chunks.unsafeIterator();
+ while (chunkIterator.hasNext()){
+ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
+
+ targetChunk.getChunkHot().nextTick();
+ targetChunk.getChunkHot().start();
+ }
+ }
+ //KioCG end
this.tickChildren(haveTime, region); // Folia - region threading
+ // KioCG start - ChunkHot
+ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
+ final java.util.Iterator<net.minecraft.world.level.chunk.LevelChunk> chunkIterator = chunks.unsafeIterator();
+ while (chunkIterator.hasNext()){
+ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
+
+ if (!targetChunk.getChunkHot().isStarted()){
+ continue;
+ }
+
+ targetChunk.getChunkHot().stop();
+ }
+ }
+ //KioCG end
if (false && nano - this.lastServerStatus >= STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading
this.lastServerStatus = nano;
this.status = this.buildServerStatus();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 2670e265d1ef57371224d831a0c8478dbe8bd43c..f2a00943b36f0cfb943bd40b5120ddbf8b7bcf7c 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1487,6 +1487,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
public void tickNonPassenger(final Entity entity) {
// Paper start - log detailed entity tick information
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
+ LevelChunk levelChunk = entity.shouldTickHot() ? this.getChunkIfLoaded(entity.moonrise$getSectionX(),entity.moonrise$getSectionZ()) : null; // KioCG
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
try {
// Folia - region threading
// Paper end - log detailed entity tick information
@@ -1563,6 +1565,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
} finally {
// Folia - region threading
}
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Paper end - log detailed entity tick information
}
@@ -1574,6 +1577,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
final int timerId = isActive ? entity.getType().tickTimerId : entity.getType().inactiveTickTimerId;
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler();
foliaProfiler.startTimer(timerId);
+ LevelChunk levelChunk = !(entity instanceof Player) ? this.getChunkIfLoaded(entity.blockPosition()) : null; // KioCG
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
try {
// Folia end - profiler
entity.setOldPosAndRot();
@@ -1615,6 +1620,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
this.tickPassenger(entity, passenger, isActive); // Paper - EAR 2
}
} finally { foliaProfiler.stopTimer(timerId); } // Folia - profiler
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 1cafca1758e7fcac59a3b3dadf28b432da82e51a..306bac1feb35b2957a6acd2b394bdd3d500e6191 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -889,6 +889,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@Override
public void tick() {
+ // Shiroha start - Add status bars
+ this.statusBarList.tick();
+ // Shiroha end - Add status bars
// CraftBukkit start
if (this.joining) {
this.joining = false;
@@ -949,7 +952,34 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.trackEnteredOrExitedLavaOnVehicle();
this.updatePlayerAttributes();
this.advancements.flushDirty(this, true);
+
+ // KioCG start - ChunkHot
+ if (this.tickCount % 20 == 0){
+ this.nearbyChunkHot = this.refreshNearbyChunkHot();
+ }
+ // KioCG end
+ }
+
+ // KioCG start - ChunkHot
+ private volatile long nearbyChunkHot = 0;
+
+ public long getNearbyChunkHot() { return this.nearbyChunkHot; }
+
+ private long refreshNearbyChunkHot() {
+ long total = 0L;
+ int searchRadius = ((ServerLevel) this.level()).moonrise$getViewDistanceHolder().getViewDistances().tickViewDistance();
+ for (int i = this.moonrise$getSectionX() - searchRadius; i <= this.moonrise$getSectionX() + searchRadius; ++i) {
+ for (int j = this.moonrise$getSectionZ() - searchRadius; j <= this.moonrise$getSectionZ() + searchRadius; ++j) {
+ net.minecraft.world.level.chunk.LevelChunk targetChunk = this.level().getChunkIfLoaded(i, j);
+ if (targetChunk != null) {
+ total += targetChunk.getChunkHot().getAverage();
+ }
+ }
+ }
+ return total;
}
+ // KioCG end
+
private void updatePlayerAttributes() {
AttributeInstance blockInteractionRange = this.getAttribute(Attributes.BLOCK_INTERACTION_RANGE);
diff --git a/net/minecraft/world/entity/AreaEffectCloud.java b/net/minecraft/world/entity/AreaEffectCloud.java
index f03fa06c0ba56f7f5e1e45bc1568a490751efde3..eee1c14249addbf4714df733870da9747bda2245 100644
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -415,4 +415,11 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
return super.applyImplicitComponent(type, value);
}
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return false;
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 9b5a0c19b5b5dd278ab7db831eef2a97010d7f58..de6a71616f62c0b1b373840102012cec06703081 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -6428,4 +6428,6 @@ public abstract class Entity
return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition());
}
// Paper end
+
+ public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
}
diff --git a/net/minecraft/world/entity/LightningBolt.java b/net/minecraft/world/entity/LightningBolt.java
index 5b19fee8a4861e5dbfb545bbe4dabda7787c430a..0afca6f5f5b02609fd55e9ea4d72b8862cc03420 100644
--- a/net/minecraft/world/entity/LightningBolt.java
+++ b/net/minecraft/world/entity/LightningBolt.java
@@ -283,4 +283,11 @@ public class LightningBolt extends Entity {
public final boolean hurtServer(final ServerLevel level, final DamageSource source, final float damage) {
return false;
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return false;
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index f421702fef63846bffaf55061c3f9c1bb1248bfa..60db243d8d9680900f75238e93740b08307f2086 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -1735,4 +1735,11 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
public float chargeSpeedModifier() {
return 1.0F;
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return super.shouldTickHot() && (!this.removeWhenFarAway(0.0) || this.isPersistenceRequired() || this.requiresCustomPersistence());
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/animal/equine/TraderLlama.java b/net/minecraft/world/entity/animal/equine/TraderLlama.java
index 7c92c9335997cee76ff360c51f704ee41a180796..fb4cab83fd23c5561326a58683558e9a4219b0e9 100644
--- a/net/minecraft/world/entity/animal/equine/TraderLlama.java
+++ b/net/minecraft/world/entity/animal/equine/TraderLlama.java
@@ -164,4 +164,11 @@ public class TraderLlama extends Llama {
super.start();
}
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return super.shouldTickHot() && !this.canDespawn();
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
index f79353aa58b03d00839e4e95d1fd2480a635a592..0a43947bcc9f505ad9bc4d54c564709c2c3e411a 100644
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
@@ -271,4 +271,11 @@ public class WanderingTrader extends AbstractVillager implements Consumable.Over
return !pos.closerToCenterThan(this.trader.position(), distance);
}
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return false;
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 5ffcf20d06f8a0cc0394347d8ef4cfa1e89ebab2..4e64eb78a4e3af2c23bdd9f61f77630b71ce97f4 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -170,6 +170,7 @@ public abstract class Player extends Avatar implements ContainerUser {
private ItemStack lastItemInMainHand = ItemStack.EMPTY;
private final ItemCooldowns cooldowns = this.createItemCooldowns();
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
+ public io.nanachiyo0721.shiroha.functions.bars.TickableStatusBarList statusBarList = new io.nanachiyo0721.shiroha.functions.bars.TickableStatusBarList(this); // Shiroha - Add status bars
public @Nullable FishingHook fishing;
public float hurtDir;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
@@ -679,6 +680,7 @@ public abstract class Player extends Avatar implements ContainerUser {
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.abilities.getWalkingSpeed());
this.enderChestInventory.fromSlots(input.listOrEmpty("EnderItems", ItemStackWithSlot.CODEC));
this.setLastDeathLocation(input.read("LastDeathLocation", GlobalPos.CODEC));
+ this.statusBarList.load(input); // Shiroha - Add status bars
}
@Override
@@ -697,6 +699,7 @@ public abstract class Player extends Avatar implements ContainerUser {
output.store("abilities", Abilities.Packed.CODEC, this.abilities.pack());
this.enderChestInventory.storeAsSlots(output.list("EnderItems", ItemStackWithSlot.CODEC));
this.lastDeathLocation.ifPresent(pos -> output.store("LastDeathLocation", GlobalPos.CODEC, pos));
+ this.statusBarList.save(output); // Shiroha - Add status bars
}
@Override
@@ -2255,4 +2258,12 @@ public abstract class Player extends Avatar implements ContainerUser {
public static final Player.BedSleepingProblem NOT_SAFE = new Player.BedSleepingProblem(Component.translatable("block.minecraft.bed.not_safe"));
public static final Player.BedSleepingProblem EXPLOSION = new Player.BedSleepingProblem(null); // Paper - Added to properly handle explosions in bed events
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return false;
+ }
+ // KioCG end
+
}
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
index 67d01bb84cd40a3f67de441e9dbdc2ac7638cada..721e3b083846fd363a31311196bc4c681969215c 100644
--- a/net/minecraft/world/entity/projectile/Projectile.java
+++ b/net/minecraft/world/entity/projectile/Projectile.java
@@ -512,4 +512,11 @@ public abstract class Projectile extends Entity implements TraceableEntity {
public interface ProjectileFactory<T extends Projectile> {
T create(final ServerLevel level, LivingEntity entity, ItemStack itemStack);
}
+
+ // KioCG start
+ @Override
+ public boolean shouldTickHot() {
+ return false;
+ }
+ // KioCG end
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 64e0c4a60a74cd33f2b99f34fa2a419abf3a0c02..0e84b695a677e71f443a29c78fc5025eec7ae7f4 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -112,6 +112,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
// Paper start - rewrite chunk system
private boolean postProcessingDone;
private ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkAndHolder;
+ private final com.kiocg.ChunkHot chunkHot = new com.kiocg.ChunkHot(); public com.kiocg.ChunkHot getChunkHot() { return this.chunkHot; } // KioCG
@Override
public final boolean moonrise$isPostProcessingDone() {
@@ -960,6 +961,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
ProfilerFiller profiler = Profiler.get();
profiler.push(this::getType);
foliaProfiler.startTimer(timerId); try { // Folia - profiler
+ LevelChunk.this.chunkHot.startTicking(); // KioCG
BlockState blockState = LevelChunk.this.getBlockState(pos);
if (this.blockEntity.getType().isValid(blockState)) {
this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity);
@@ -979,7 +981,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
);
} // Paper - Remove the Block Entity if it's invalid
}
- } finally { foliaProfiler.stopTimer(timerId); } // Folia - profiler
+ } finally { foliaProfiler.stopTimer(timerId); LevelChunk.this.chunkHot.stopTickingAndCount(); } // Folia - profiler // KioCG
profiler.pop();
} catch (Throwable t) {
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
index 041ed95948ff6bb4cf3610ce4522a6ba105b6812..44dbe6f83c8593c213132feabc7fe27615cb0049 100644
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
@@ -81,7 +81,10 @@ public interface NeighborUpdater {
return;
}
// CraftBukkit end
+ net.minecraft.world.level.chunk.LevelChunk levelChunk = level.getChunkIfLoaded(pos); // KioCG
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
state.handleNeighborChanged(level, pos, changedBlock, orientation, movedByPiston);
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Spigot start
} catch (StackOverflowError ex) {
level.lastPhysicsProblem = pos.immutable();