From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Wed, 4 Dec 2024 23:53:03 +0800 Subject: [PATCH] KioCG Chunk API and display of chunkhot in tpsbar diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java index 30eb7fd0b83ad1626d337cb770fac3dda5202344..cbe8f1fce4327bcc2a677b3da268cf52fef90335 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java @@ -127,6 +127,7 @@ public final class ChunkSystem { } public static void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) { + chunk.getChunkHot().clear(); // KioCG chunk.getLevel().getCurrentWorldData().removeTickingChunk(chunk.moonrise$getChunkAndHolder()); // Folia - region threading ((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration } diff --git a/src/main/java/com/kiocg/ChunkHot.java b/src/main/java/com/kiocg/ChunkHot.java new file mode 100644 index 0000000000000000000000000000000000000000..53b4397997bc9b9b9d88e48304b37a2590161906 --- /dev/null +++ b/src/main/java/com/kiocg/ChunkHot.java @@ -0,0 +1,90 @@ +package com.kiocg; + +import java.util.Arrays; + +public class ChunkHot { + // 热度统计总区间数量 + private static final int TIMES_LENGTH = 10; + // 当前统计区间下标 + private int index = -1; + + // 热度统计区间 + private final long[] times = new long[TIMES_LENGTH]; + // 存放临时的区间数值 + // 用于修正正在统计的当前区间热度没有计入总值的问题 + private long temp; + // 所有区间的热度总值 + private long total; + + // 用于每个具体统计的计算 + private long nanos; + // 当前统计是否进行中 + private volatile boolean started = false; + + /** + * 更新区间下标 + */ + public void nextTick() { + this.index = ++this.index % TIMES_LENGTH; + } + + /** + * 开始统计一个新区间 + */ + public void start() { + started = true; + temp = times[this.index]; + times[this.index] = 0L; + } + + public boolean isStarted(){ + return this.started; + } + + /** + * 结束当前区间的统计 + * 将统计值更新入热度总值 + */ + public void stop() { + started = false; + total -= temp; + total += times[this.index]; + } + + /** + * 开始一个具体统计 + */ + public void startTicking() { + if (!started) return; + nanos = System.nanoTime(); + } + + /** + * 结束一个具体统计 + * 将统计值计入当前热度区间 + */ + public void stopTickingAndCount() { + if (!started) return; + // 定义一个具体统计的最大值为 1,000,000 + // 有时候某个具体统计的计算值会在某1刻飙升,可能是由于保存数据到磁盘? + times[this.index] += Math.min(System.nanoTime() - nanos, 1000000L); + } + + /** + * 清空统计 (当区块卸载时) + */ + public void clear() { + started = false; + Arrays.fill(times, 0L); + temp = 0L; + total = 0L; + nanos = 0L; + } + + /** + * @return 获取区块热度平均值 + */ + public long getAverage() { + return total / ((long) TIMES_LENGTH * 20L); + } +} diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java index aafb2f5052c7c8e5971a47308253badb3027093c..9fe7ac7ba83bbcc9a2a851a5cace47641323f4d2 100644 --- a/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java +++ b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java @@ -12,11 +12,13 @@ public class TpsBarConfig implements IConfigModule { @ConfigInfo(baseName = "enabled") public static boolean tpsbarEnabled = false; @ConfigInfo(baseName = "format") - public static String tpsBarFormat = "TPS: MSPT: Ping: ms"; + public static String tpsBarFormat = "TPS: MSPT: Ping: ms ChunkHot: "; @ConfigInfo(baseName = "tps_color_list") public static List tpsColors = List.of("GREEN","YELLOW","RED","PURPLE"); @ConfigInfo(baseName = "ping_color_list") public static List pingColors = List.of("GREEN","YELLOW","RED","PURPLE"); + @ConfigInfo(baseName = "chunkhot_color_list") + public static List chunkHotColors = List.of("GREEN","YELLOW","RED","PURPLE"); @ConfigInfo(baseName = "update_interval_ticks") public static int updateInterval = 15; diff --git a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java index de2f03d6e771c09e8da2da454b7ec4a16c0a17ab..0b7347e8fdf995900221ee4aa4e97a4d260c6f9f 100644 --- a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java +++ b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java @@ -128,7 +128,8 @@ public class GlobalServerTpsBar { TpsBarConfig.tpsBarFormat, Placeholder.component("tps",getTpsComponent(tps)), Placeholder.component("mspt",getMsptComponent(mspt)), - Placeholder.component("ping",getPingComponent(player.getPing())) + Placeholder.component("ping",getPingComponent(player.getPing())), + Placeholder.component("chunkhot",getChunkHotComponent(player.getNearbyChunkHot())) )); bar.color(barColorFromTps(tps)); bar.progress((float) Math.min((float)1,Math.max(mspt / 50,0))); @@ -170,6 +171,32 @@ public class GlobalServerTpsBar { return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.format("%.2f", mspt))); } + private static @NotNull Component getChunkHotComponent(long chunkHot){ + final BossBar.Color colorBukkit = barColorFromChunkHot(chunkHot); + final String colorString = colorBukkit.name(); + + final String content = "<%s>"; + final String replaced = String.format(content,colorString,colorString); + + return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.valueOf(chunkHot))); + } + + private static BossBar.Color barColorFromChunkHot(long chunkHot){ + if (chunkHot == -1){ + return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(3)); + } + + if (chunkHot <= 300000L){ + return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(0)); + } + + if (chunkHot <= 500000L){ + return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(1)); + } + + return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(2)); + } + private static BossBar.Color barColorFromMspt(double mspt){ if (mspt == -1){ return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3)); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 55bac6e6cccce6e0282936ac78bbe82628daa655..2cff9edf247587dffaac5405127de0afc17dc7c0 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1801,6 +1801,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop chunks = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); + if (region != null){ + 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 Iterator chunkIterator = chunks.unsafeIterator(); + while (chunkIterator.hasNext()){ + final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next(); + + targetChunk.getChunkHot().nextTick(); + targetChunk.getChunkHot().start(); + } + } + //KioCG end if (region == null) this.tickRateManager.tick(); // Folia - region threading this.tickChildren(shouldKeepTicking, region); // Folia - region threading if (region == null && i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading @@ -1809,6 +1832,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 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 // Paper start - Incremental chunk and player saving final ProfilerFiller profiler = Profiler.get(); int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 98aef7a3cfc759e4415df3a56b5fe01eb50b0428..f8dfaa6170962f5b06a0a8ccbf3d8677381babcf 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1382,6 +1382,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe final int timerId = isActive ? entity.getType().tickTimerId : entity.getType().inactiveTickTimerId; final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); profiler.startTimer(timerId); + LevelChunk levelChunk = entity.shouldTickHot() ? this.getChunkIfLoaded(entity.moonrise$getSectionX(),entity.moonrise$getSectionZ()) : null; // KioCG + if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG try { // Folia end - profiler if (isActive) { // Paper - EAR 2 @@ -1399,6 +1401,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } else { entity.inactiveTick(); } // Paper - EAR 2 gameprofilerfiller.pop(); } finally { profiler.stopTimer(timerId); } // Folia - timer + } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { @@ -1421,6 +1424,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe final int timerId = isActive ? passenger.getType().tickTimerId : passenger.getType().inactiveTickTimerId; final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); profiler.startTimer(timerId); + LevelChunk levelChunk = !(passenger instanceof Player) ? this.getChunkIfLoaded(passenger.blockPosition()) : null; // KioCG + if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG try { // Folia end - profiler passenger.setOldPosAndRot(); @@ -1461,6 +1466,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } } finally { profiler.stopTimer(timerId); } // Folia - profiler + } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG } } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index c72bda7413d9a7ce763743d0efbd85257262477e..96880fffd92cff3f172a3ded55534eefbb0a740a 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -359,6 +359,26 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple } // Paper end - rewrite chunk system + // 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 + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); this.chatVisibility = ChatVisiblity.FULL; @@ -1199,6 +1219,12 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.trackEnteredOrExitedLavaOnVehicle(); this.updatePlayerAttributes(); this.advancements.flushDirty(this); + + // KioCG start - ChunkHot + if (this.tickCount % 20 == 0){ + this.nearbyChunkHot = this.refreshNearbyChunkHot(); + } + // KioCG end } private void updatePlayerAttributes() { diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java index 921527acc8624536f4a48e9fdf7fce370bc52c77..497de02dce0f397ce261b4d62777e11f67324bde 100644 --- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java +++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java @@ -481,4 +481,11 @@ public class AreaEffectCloud extends Entity implements TraceableEntity { public final boolean hurtServer(ServerLevel world, DamageSource source, float amount) { return false; } + + // KioCG start + @Override + public boolean shouldTickHot() { + return false; + } + // KioCG end } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index b6aaa238626bc747379f991c17c279de52907083..3700f7c1893e9ccdcef04ae1fab5d7c97c5a91d7 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -6236,4 +6236,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return ((net.minecraft.server.level.ServerLevel) this.level).isPositionEntityTicking(this.blockPosition()); } // Paper end - Expose entity id counter + + public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG } diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java index 12127b14babf646711d3a118416453c4f1ac1460..5929cd58066b1a8f305b411af8ac4abc688a5cc6 100644 --- a/src/main/java/net/minecraft/world/entity/LightningBolt.java +++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java @@ -302,4 +302,11 @@ public class LightningBolt extends Entity { public final boolean hurtServer(ServerLevel world, DamageSource source, float amount) { return false; } + + // KioCG start + @Override + public boolean shouldTickHot() { + return false; + } + // KioCG end } diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java index 5280e0bd88b39a2f1ca62b03ed2c54a89df4f212..b6b5837df2bcd229425e27b513a47922748c01ff 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -1855,4 +1855,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab public float[] getArmorDropChances() { return this.armorDropChances; } + + // KioCG start + @Override + public boolean shouldTickHot() { + return super.shouldTickHot() && (!this.removeWhenFarAway(0.0) || this.isPersistenceRequired() || this.requiresCustomPersistence()); + } + // KioCG end } diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java index 53a8d59681809da931d11ff76c202f950993a142..3a3cf979d79c270a5f873ff62b5618b832a34fed 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/TraderLlama.java @@ -173,4 +173,11 @@ public class TraderLlama extends Llama { super.start(); } } + + // KioCG start + @Override + public boolean shouldTickHot() { + return super.shouldTickHot() && !this.canDespawn(); + } + // KioCG end } diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java index 1e77cce428d9e53142aaa2cf780b7f862d536eca..f5bad1a9f274cb5a1bdf54a4c575afaa4ab7328f 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java @@ -327,4 +327,12 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill return !pos.closerToCenterThan(this.trader.position(), proximityDistance); } } + + + // KioCG start + @Override + public boolean shouldTickHot() { + return false; + } + // KioCG end } 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 f2817f1c29431ef2c4a45dc9ef90f06d4982f7c9..77e607f35d1a76046869f5900321263927344e4c 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -2447,6 +2447,13 @@ public abstract class Player extends LivingEntity { return this.abilities.flying ? false : super.onClimbable(); } + // KioCG start + @Override + public boolean shouldTickHot() { + return false; + } + // KioCG end + public static enum BedSleepingProblem { NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")), TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")), OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")), OTHER_PROBLEM, NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe")); diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java index 7ccd7d6dc61948210ecb9c3acee8f1740e389106..04f3e62f41d4bf0fc5b98d24b72789e00110f626 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java @@ -566,4 +566,11 @@ public abstract class Projectile extends Entity implements TraceableEntity { T create(ServerLevel world, LivingEntity shooter, ItemStack stack); } + + // KioCG start + @Override + public boolean shouldTickHot() { + return false; + } + // KioCG end } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java index 6003e3495e61073c39928918b9d9f4c2e20f3a49..bb4053a89a737a0ba4a09afe821924967fbea004 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -95,6 +95,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p private final LevelChunkTicks blockTicks; private final LevelChunkTicks fluidTicks; private LevelChunk.UnsavedListener unsavedListener; + private final com.kiocg.ChunkHot chunkHot = new com.kiocg.ChunkHot(); public com.kiocg.ChunkHot getChunkHot() { return this.chunkHot; } // KioCG public LevelChunk(Level world, ChunkPos pos) { this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); @@ -1085,6 +1086,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p ProfilerFiller gameprofilerfiller = Profiler.get(); gameprofilerfiller.push(this::getType); + LevelChunk.this.chunkHot.startTicking(); // KioCG profiler.startTimer(timerId); try { // Folia - profiler BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); @@ -1100,7 +1102,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p } // Paper end - Remove the Block Entity if it's invalid } - } finally { profiler.stopTimer(timerId); } // Folia - profiler + } finally { profiler.stopTimer(timerId); LevelChunk.this.chunkHot.stopTickingAndCount(); } // Folia - profiler // KioCG gameprofilerfiller.pop(); } catch (Throwable throwable) { 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 e414da8a51bb9b49c28a74eca166046cbee44835..ac22bb47836e97904729bad91ff75ce7abfb30b6 100644 --- a/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/NeighborUpdater.java @@ -73,7 +73,10 @@ public interface NeighborUpdater { } } // CraftBukkit end + net.minecraft.world.level.chunk.LevelChunk levelChunk = world.getChunkIfLoaded(pos); // KioCG + if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG state.handleNeighborChanged(world, pos, sourceBlock, orientation, notify); + } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG // Spigot Start } catch (StackOverflowError ex) { world.lastPhysicsProblem = new BlockPos(pos); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java index c2bffe3450ee9f768e00a23ec09df74d7a06d49b..4791e013e8257f57b5db6f974dc05829b911cfa0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java @@ -437,4 +437,12 @@ public class CraftChunk implements Chunk { static { Arrays.fill(FULL_LIGHT, (byte) 0xFF); } + + // KioCG start - ChunkHot + @Override + public long getChunkHotAvg() { + final net.minecraft.world.level.chunk.LevelChunk target = this.worldServer.getChunkIfLoaded(this.x,this.z); + return target == null ? -1 : target.getChunkHot().getAverage(); + } + // KioCG end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index bf9cf758c7aef50d34e2017665b6d3f4125228f5..7cb4389e1a03655d00cd19ad43019c5ff14785f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -3596,4 +3596,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData())); } // Paper end - entity effect API + + // KioCG start - ChunkHot + @Override + public long getNearbyChunkHot() { + return this.getHandle().getNearbyChunkHot(); + } + // KioCG end }