Compare commits

...

9 Commits

Author SHA1 Message Date
Helvetica Volubi fa1ab90579 fix a ConcurrentModificationException caused by ServuxStructuresProtocol
Update Luminol
2025-11-30 15:53:28 +08:00
Creeam fc9c6937b6 Add LeavesConfig dummy class (#99)
For some plugin detections
2025-11-30 07:28:01 +00:00
Helvetica Volubi 12d8ba9050 Update Luminol 2025-11-29 06:03:01 +08:00
Helvetica Volubi 38a1ce0443 fix: fix crash caused by uncheck data access 2025-11-26 22:32:20 +08:00
dependabot[bot] a5a415e495 build(deps): bump actions/checkout from 5 to 6 (#93)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 08:21:49 +00:00
Helvetica Volubi b7bf1b5916 Update Luminol 2025-11-24 00:16:50 +08:00
Helvetica Volubi 4a8888c578 try fixes bugs caused by Bukkit.getScheduler().runTaskLater
we use (FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed to instead of Bukkit.getScheduler().runTaskLater, and we also provided a brand-new way to cancel task by task id
2025-11-22 01:57:16 +08:00
Helvetica Volubi 2c59a32afe [ci skip] Update context 2025-11-20 15:36:46 +08:00
Helvetica Volubi cc5382977d Update Luminol 2025-11-20 15:32:41 +08:00
16 changed files with 134 additions and 23 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
name: Bug反馈 Bug report
description:
报告Bug,插件不兼容情况,以及其他相关问题。
Report issues with plugin incompatbility or other behavior related issues.
Report issues with plugin incompatibility or other behavior related issues.
labels:
- bug
- pending
@@ -41,7 +41,7 @@ body:
attributes:
label: 观测到的实际行为 Observed/Actual behavior
description: 你实际看到的。 What you actually saw.
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
validations:
required: true
- type: textarea
+1 -1
View File
@@ -28,7 +28,7 @@ body:
validations:
required: true
- type: textarea
id: othre
id: other
attributes:
label: 其他 Other
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
environment: default
steps:
- name: Checkout Git Repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Set Up JDK
uses: actions/setup-java@v5
+1 -1
View File
@@ -4,7 +4,7 @@ mcVersion=1.21.8
release=2
# 0 for skip release, 1 for pre-release, 2 for release
luminolRef=3032dbc331d34b229440b8935287711bf2557306
luminolRef=ae1af655f57cd8666c2ae913fa53d3606019bf7b
org.gradle.configuration-cache=true
org.gradle.caching=true
@@ -5,10 +5,10 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index a5208f5426ea2e5d8f50c51fe17718ea1d63eef5..c80c578f1a3786bd7413c9a7af8ae125fe7975bb 100644
index 0bebc2cc87fb9c1c526e4de4f3bc157552307a72..cb1657939b86c039fcfe6403d3f202c2c5879e88 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -21,6 +21,7 @@ public class ConfigManager {
@@ -23,6 +23,7 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
@@ -5,10 +5,10 @@ Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index f3d07efc347ff3cd06011484af0e75b5d93e6ec7..52f520667abba68af88834a771b6bcb40d1bd806 100644
index d0de3b22f6cef6eb213b7ff688a514a67f84fbcf..3b39b8f7ccb278cf910e3cc4e00da29790465a81 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -519,7 +519,7 @@ public final class RegionizedWorldData {
@@ -524,7 +524,7 @@ public final class RegionizedWorldData {
this.world = world;
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
@@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 22 Nov 2025 01:43:26 +0800
Subject: [PATCH] add cancel task by task id in FoliaGlobalRegionScheduler
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
index d306f911757a4d556c82c0070d4837db87afc497..7c9d3e4c399b2ea246a76b4550ba12e45e75078e 100644
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
@@ -17,6 +17,8 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private long tickCount = 0L;
private final Object stateLock = new Object();
private final Long2ObjectOpenHashMap<List<GlobalScheduledTask>> tasksByDeadline = new Long2ObjectOpenHashMap<>();
+ private int lastTaskId = 1; // Lophine - add task id
+ private final Object stateLockForTaskId = new Object(); // Lophine - add task id
public void tick() {
final List<GlobalScheduledTask> run;
@@ -65,7 +67,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, delayTicks);
@@ -92,7 +94,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, initialDelayTicks);
@@ -134,7 +136,33 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
- private final class GlobalScheduledTask implements ScheduledTask, Runnable {
+ // Lophine start - add cancel task by task id
+ public void cancelTask(final int taskId) {
+ synchronized (this.stateLock) {
+ for (final List<GlobalScheduledTask> tasks : this.tasksByDeadline.values()) {
+ for (final GlobalScheduledTask task : tasks) {
+ if (task.getTaskId() == taskId) {
+ task.cancel();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private int getNextTaskId() {
+ synchronized (this.stateLockForTaskId) {
+ if (this.lastTaskId == Integer.MAX_VALUE) {
+ this.lastTaskId = 1;
+ } else {
+ ++this.lastTaskId;
+ }
+ }
+ return this.lastTaskId;
+ }
+ // Lophine end - add cancel task by task id
+
+ public final class GlobalScheduledTask implements ScheduledTask, Runnable { // Lophine - private -> public
private static final int STATE_IDLE = 0;
private static final int STATE_EXECUTING = 1;
@@ -146,13 +174,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private final long repeatDelay; // in ticks
private Consumer<ScheduledTask> run;
private volatile int state;
+ private int taskId; // Lophine - add task id
private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
- private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run) {
+ private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run, int taskId) { // Lophine - add task id
this.plugin = plugin;
this.repeatDelay = repeatDelay;
this.run = run;
+ this.taskId = taskId; // Lophine - add task id
}
private final int getStateVolatile() {
@@ -263,5 +293,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
}
+
+ // Lophine start - add task id
+ public int getTaskId() {
+ return taskId;
+ }
+ // Lophine end - add task id
}
}
@@ -3,8 +3,6 @@ package fun.bm.lophine;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.util.logging.Level;
public class LophineLogger {
public static final Logger LOGGER = LogUtils.getClassLogger(); // only provided for some Logger can not be initialized
}
@@ -6,10 +6,11 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
/*
* This is a config module for redstone in experimental level
* If we think configs from here is stable for future, we will move them to function module directory
*/
* This is a config module for redstone in experimental level
* If we think configs from here is stable for future, we will move them to function module directory
*/
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"experiment", "redstone-ignore-upwards-update"})
@@ -8,6 +8,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "update-suppression-crash-fix")
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Should crashes caused by update suppression be prevented?""")
Should crash caused by update suppression be prevented?""")
public static boolean enabled = true;
}
@@ -0,0 +1,4 @@
package org.leavesmc.leaves;
public class LeavesConfig {
}
@@ -25,6 +25,7 @@ import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.RegionizedServer;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.minecraft.nbt.CompoundTag;
@@ -238,7 +239,7 @@ public class BotList {
}
if (bot.removeTaskId != -1) {
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
bot.removeTaskId = -1;
}
@@ -473,7 +473,7 @@ public class ServerBot extends ServerPlayer {
playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity));
if (login) {
Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
} else {
playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f)));
}
@@ -499,7 +499,7 @@ public class ServerBot extends ServerPlayer {
Component defaultMessage = this.getCombatTracker().getDeathMessage();
BotDeathEvent event = new BotDeathEvent(this.getBukkitEntity(), PaperAdventure.asAdventure(defaultMessage), flag);
this.getServer().server.getPluginManager().callEvent(event);
MinecraftServer.getServer().server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (this.getHealth() <= 0) {
@@ -20,6 +20,7 @@ package org.leavesmc.leaves.command.bot.subcommands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -102,12 +103,12 @@ public class RemoveCommand extends BotSubcommand {
boolean isReschedule = bot.removeTaskId != -1;
if (isReschedule) {
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
}
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
bot.removeTaskId = ((FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> {
bot.removeTaskId = -1;
removeBot(bot, sender);
}, removeTimeSeconds * 20L).getTaskId();
}, removeTimeSeconds * 20L)).getTaskId();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
@@ -17,6 +17,7 @@
package org.leavesmc.leaves.protocol.servux;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.protocol.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
@@ -31,6 +32,7 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
@@ -104,6 +106,7 @@ public class ServuxEntityDataProtocol implements LeavesProtocol {
public static void onBlockEntityRequest(ServerPlayer player, BlockPos pos) {
player.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
if (!TickThread.isTickThreadFor(nmsEntity.level(), pos)) return;
BlockEntity be = nmsEntity.level().getBlockEntity(pos);
CompoundTag nbt = be != null ? be.saveWithFullMetadata(nmsEntity.registryAccess()) : new CompoundTag();
@@ -115,7 +118,9 @@ public class ServuxEntityDataProtocol implements LeavesProtocol {
}
public static void onEntityRequest(ServerPlayer player, int entityId) {
final Vec3 pos = player.position();
player.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
if (!TickThread.isTickThreadFor(nmsEntity.level(), pos)) return;
Entity entity = nmsEntity.level().getEntity(entityId);
CompoundTag nbt = TagUtil.saveEntityWithoutId(entity);
@@ -103,7 +103,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
final ChunkPos pos = chunk.getPos();
if (chunkHasStructureReferences(pos.x, pos.z, chunk.getLevel())) {
final Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new HashMap<>());
final Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new ConcurrentHashMap<>());
map.computeIfAbsent(pos, (p) -> new Timeout(tickCounter - ServuxProtocolConfig.maxDelay));
}
}
@@ -304,7 +304,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
}
public static void addOrRefreshTimeouts(final UUID uuid, final Map<Structure, LongSet> references, final long tickCounter) {
Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new HashMap<>());
Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new ConcurrentHashMap<>());
for (LongSet chunks : references.values()) {
for (Long chunkPosLong : chunks) {