Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cdc69ecc09 | |||
| 7f0c8a2706 | |||
| 47bc8042d2 | |||
| 03849ba73c | |||
| ef3d1625b8 | |||
| c4acc049d8 | |||
| 3dc7b1edb7 | |||
| ab2992a2ef | |||
| 5622d49d49 | |||
| 7fdce6aedd | |||
| c26d8d1ee3 | |||
| 7bc12d2487 | |||
| 2c3aa4b68e | |||
| 91312b7a15 | |||
| 77c412bfe8 | |||
| c06d875df7 | |||
| 5e96851513 |
@@ -74,11 +74,11 @@ body:
|
||||
All config files on your server.
|
||||
例如以下文件(或者文件夹):
|
||||
Example files (or folders):
|
||||
- \spigot.yml
|
||||
- \bukkit.yml
|
||||
- \config\\\*
|
||||
- \lophine_config\\\*
|
||||
- \luminol_config\\\*
|
||||
- \spigot.yml
|
||||
- \bukkit.yml
|
||||
- \config\\\*
|
||||
- \lophine_config\\\*
|
||||
- \luminol_config\\\*
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
|
||||
@@ -14,7 +14,7 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
force-push:
|
||||
description: "Force disable push to repo if you enter 2, push to repo if you enter 1, default push if not released else skip push repo"
|
||||
description: "Force disable push to repo if you enter 2, force push to repo if you enter 1, default push if not released else skip push repo"
|
||||
required: false
|
||||
default: ""
|
||||
comments:
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: ${{ env.project_id_b }} CI Artifacts
|
||||
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Publish To Repo
|
||||
if: (( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1') && false # do not push to any repo
|
||||
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1'
|
||||
continue-on-error: true
|
||||
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
|
||||
env:
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
|
||||
fetch-depth: 0 # a full history is required for pull request analysis
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2025.2
|
||||
uses: JetBrains/qodana-action@latest
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
|
||||
+3
-5
@@ -6,12 +6,10 @@ build
|
||||
|
||||
/run
|
||||
|
||||
/lightingluminol-server/build.gradle.kts
|
||||
/lightingluminol-api/build.gradle.kts
|
||||
/luminol-server/build.gradle.kts
|
||||
/luminol-server/src/minecraft
|
||||
/lophine-server/build.gradle.kts
|
||||
/lophine-api/build.gradle.kts
|
||||
/lophine-server/src/minecraft
|
||||
/paper-server
|
||||
/luminol-api/build.gradle.kts
|
||||
/paper-api
|
||||
/paper-api-generator
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -78,7 +78,7 @@ dependencies {
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
</dependency>
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -78,7 +78,7 @@ dependencies {
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
<scope>provided</scope>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ mcVersion=1.21.8
|
||||
release=2
|
||||
# 0 for skip release, 1 for pre-release, 2 for release
|
||||
|
||||
luminolRef=46252869190560b69e97c474e91aaa07ac480436
|
||||
luminolRef=170d047a69f8e4711651f475d6a795878651b1eb
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 16 Jan 2026 02:34:43 +0800
|
||||
Subject: [PATCH] Add config to enable save-all command
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..6deaeaf95a43e217f65d3e0764b844ff4573d4ca 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -317,6 +317,8 @@ public final class RegionizedServer {
|
||||
// tick player ping sample
|
||||
this.tickPlayerSample();
|
||||
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.checkTimeout(); // Lophine - save-all fix
|
||||
+
|
||||
// tick worlds
|
||||
for (final ServerLevel world : this.worlds) {
|
||||
this.globalTick(world, tickCount);
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegions.java b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
index bfb39cbf1ba58d02da7e35300eb95872747506e8..25e8f26f708b68bd90f57863e7833e6502d981e2 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegions.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
@@ -168,6 +168,8 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
|
||||
public final ThreadedRegionizer.ThreadedRegion<TickRegionData, TickRegionSectionData> region;
|
||||
public final ServerLevel world;
|
||||
|
||||
+ public long lastSavedTime = 0; // Lophine - save-all fix
|
||||
+
|
||||
// generic regionised data
|
||||
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 25ccbfa12d57d540195ecc16aa54a144f8ecc0e8..c00e0e74cb4c820a5c8b3722ebc1ff56318dae02 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -277,7 +277,11 @@ public class Commands {
|
||||
PardonCommand.register(this.dispatcher);
|
||||
PardonIpCommand.register(this.dispatcher);
|
||||
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
- //SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ // Lophine start - Add a config to enable save all command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.saveAll) {
|
||||
+ SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable save all command
|
||||
SaveOffCommand.register(this.dispatcher);
|
||||
SaveOnCommand.register(this.dispatcher);
|
||||
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 75027e73859c955a54034640f905cb5d91a6a2f4..1fa4110b61e49ee9527b65ecafb96b0dcd2c8ce2 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1581,6 +1581,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Folia start - region threading
|
||||
public void tickServer(long startTime, long scheduledEnd, long targetBuffer,
|
||||
io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
|
||||
+ // Lophine start - save-all fix
|
||||
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
|
||||
+ }
|
||||
+ // Lophine end - save-all fix
|
||||
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||
// Folia end - region threading
|
||||
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
index 15e0fce7500dc2dc2a712bf61d1d5506fd8f317a..71f53f057527192f8f830c7d21bd72233479fe55 100644
|
||||
--- a/net/minecraft/server/commands/SaveAllCommand.java
|
||||
+++ b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
@@ -21,7 +21,9 @@ public class SaveAllCommand {
|
||||
}
|
||||
|
||||
private static int saveAll(CommandSourceStack source, boolean flush) throws CommandSyntaxException {
|
||||
- source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
+ // Lophine start - save all
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.preSaveAll(source, flush);
|
||||
+/* source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
MinecraftServer server = source.getServer();
|
||||
boolean flag = server.saveEverything(true, flush, true);
|
||||
if (!flag) {
|
||||
@@ -29,6 +31,12 @@ public class SaveAllCommand {
|
||||
} else {
|
||||
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
|
||||
return 1;
|
||||
- }
|
||||
+ }*/
|
||||
+ return 1;
|
||||
}
|
||||
+
|
||||
+ public static SimpleCommandExceptionType getErrorFailed() {
|
||||
+ return ERROR_FAILED;
|
||||
+ }
|
||||
+ // Lophine end - save all
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable scoreboard command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 25ccbfa12d57d540195ecc16aa54a144f8ecc0e8..22d211bee83e3ef34d6ac81dd89c0e73924bee90 100644
|
||||
index c00e0e74cb4c820a5c8b3722ebc1ff56318dae02..2be7e5de57f474a3600ea4990899c1955faa512e 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -229,7 +229,11 @@ public class Commands {
|
||||
+5
-5
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable tick command
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839621d73d7 100644
|
||||
index 6deaeaf95a43e217f65d3e0764b844ff4573d4ca..1cefe9d83788dafc293aeb6d1b5e635211094b2a 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -299,6 +299,11 @@ public final class RegionizedServer {
|
||||
@@ -20,7 +20,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
||||
// expire invalid click command callbacks
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
@@ -322,6 +327,13 @@ public final class RegionizedServer {
|
||||
@@ -324,6 +329,13 @@ public final class RegionizedServer {
|
||||
this.globalTick(world, tickCount);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
@@ -455,7 +467,7 @@ public final class RegionizedServer {
|
||||
@@ -457,7 +469,7 @@ public final class RegionizedServer {
|
||||
}
|
||||
|
||||
private void tickTime(final ServerLevel world, final int tickCount) {
|
||||
@@ -97,7 +97,7 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
|
||||
this.scheduler.regionFailed(this, false, thr);
|
||||
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 22d211bee83e3ef34d6ac81dd89c0e73924bee90..1fb359073342a657e9e493403263b56be5b3393f 100644
|
||||
index 2be7e5de57f474a3600ea4990899c1955faa512e..8d332f8e99ceb5a20b3b54bc327b024968719017 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -249,7 +249,11 @@ public class Commands {
|
||||
@@ -114,7 +114,7 @@ index 22d211bee83e3ef34d6ac81dd89c0e73924bee90..1fb359073342a657e9e493403263b56b
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 75027e73859c955a54034640f905cb5d91a6a2f4..2f4970242c754cfba8ff5656a63af07d9d0a723c 100644
|
||||
index 1fa4110b61e49ee9527b65ecafb96b0dcd2c8ce2..df5ff1cc7b289c3f52723d4e7b418e79ae6c3082 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
+61
-27
@@ -6,7 +6,7 @@ Subject: [PATCH] Add config to enable waypoint command & bar
|
||||
use concurrent method to fix it (now, they are thread safe)
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 1fb359073342a657e9e493403263b56be5b3393f..451a685782da46f5683ea6707289bbaf3193771f 100644
|
||||
index 8d332f8e99ceb5a20b3b54bc327b024968719017..d4357499cbfd0474dae3c66b4473b81367f284d1 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -257,7 +257,11 @@ public class Commands {
|
||||
@@ -23,10 +23,10 @@ index 1fb359073342a657e9e493403263b56be5b3393f..451a685782da46f5683ea6707289bbaf
|
||||
WorldBorderCommand.register(this.dispatcher);
|
||||
if (JvmProfiler.INSTANCE.isAvailable()) {
|
||||
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d210760b607d7f 100644
|
||||
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..65a4956ba2f0e38da7ae4f8cd7ed6e4b02c015a9 100644
|
||||
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
@@ -16,19 +16,26 @@ import net.minecraft.world.waypoints.WaypointManager;
|
||||
@@ -16,22 +16,31 @@ import net.minecraft.world.waypoints.WaypointManager;
|
||||
import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||
|
||||
public class ServerWaypointManager implements WaypointManager<WaypointTransmitter> {
|
||||
@@ -35,7 +35,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d21076
|
||||
- private final Table<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = HashBasedTable.create();
|
||||
+ private final Set<WaypointTransmitter> waypoints = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent
|
||||
+ private final Set<ServerPlayer> players = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent
|
||||
+ private final fun.bm.lophine.utils.concurrent.ConcurrentTable<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = new fun.bm.lophine.utils.concurrent.ConcurrentTable<>(); // Lophine - concurrent
|
||||
+ private final fun.bm.lophine.utils.concurrent.AbstractConcurrentTable<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = fun.bm.lophine.config.modules.optimizations.WayPointOptimizedTableConfig.optimizedTable ? new fun.bm.lophine.utils.concurrent.OptimizedConcurrentTable<>() : new fun.bm.lophine.utils.concurrent.ConcurrentTable<>(); // Lophine - concurrent
|
||||
|
||||
@Override
|
||||
public void trackWaypoint(WaypointTransmitter waypoint) {
|
||||
@@ -54,18 +54,27 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d21076
|
||||
public void updateWaypoint(WaypointTransmitter waypoint) {
|
||||
if (this.waypoints.contains(waypoint)) {
|
||||
- Map<ServerPlayer, WaypointTransmitter.Connection> map = Tables.transpose(this.connections).row(waypoint);
|
||||
+ Map<ServerPlayer, WaypointTransmitter.Connection> map = this.connections.getXZ(waypoint); // Lophine - concurrent
|
||||
SetView<ServerPlayer> set = Sets.difference(this.players, map.keySet());
|
||||
- SetView<ServerPlayer> set = Sets.difference(this.players, map.keySet());
|
||||
+ java.util.List<Entry<ServerPlayer, WaypointTransmitter.Connection>> map = this.connections.getXZ(waypoint); // Lophine - concurrent
|
||||
+ Set<ServerPlayer> players1 = new HashSet<>(); // Lophine - concurrent
|
||||
+ if (!map.isEmpty()) map.forEach((entry) -> players1.add(entry.getKey())); // Lophine - concurrent
|
||||
+ SetView<ServerPlayer> set = Sets.difference(this.players, players1); // Lophine - concurrent
|
||||
|
||||
for (Entry<ServerPlayer, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
||||
@@ -43,26 +50,58 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
- for (Entry<ServerPlayer, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
||||
+ for (Entry<ServerPlayer, WaypointTransmitter.Connection> entry : map) { // Lophine - concurrent
|
||||
this.updateConnection(entry.getKey(), waypoint, entry.getValue());
|
||||
}
|
||||
|
||||
@@ -43,26 +52,65 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
|
||||
@Override
|
||||
public void untrackWaypoint(WaypointTransmitter waypoint) {
|
||||
- this.connections.column(waypoint).forEach((serverPlayer, connection) -> connection.disconnect());
|
||||
- Tables.transpose(this.connections).row(waypoint).clear();
|
||||
+ this.connections.getXZ(waypoint).forEach((serverPlayer, connection) -> connection.disconnect()); // Lophine - concurrent
|
||||
+ this.connections.clearXZ(waypoint); // Lophine - concurrent
|
||||
+ this.connections.getXZ(waypoint).forEach((entry) -> {
|
||||
+ entry.getValue().disconnect();
|
||||
+ this.connections.remove(entry.getKey(), waypoint, entry.getValue());
|
||||
+ }); // Lophine - concurrent
|
||||
this.waypoints.remove(waypoint);
|
||||
}
|
||||
|
||||
@@ -89,10 +98,12 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d21076
|
||||
// Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+ Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.getYZ(player); // Lophine - concurrent
|
||||
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
|
||||
+ java.util.List<Entry<WaypointTransmitter, WaypointTransmitter.Connection>> map = this.connections.getYZ(player); // Lophine - concurrent
|
||||
+ Set<WaypointTransmitter> waypoints1 = new HashSet<>();// Lophine - concurrent
|
||||
+ if (!map.isEmpty()) map.forEach((entry) -> waypoints1.add(entry.getKey()));// Lophine - concurrent
|
||||
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, waypoints1); // Lophine - concurrent
|
||||
+
|
||||
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
||||
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : map) { // Lophine - concurrent
|
||||
+ this.updateConnection(player, entry.getKey(), entry.getValue());
|
||||
+ }
|
||||
+
|
||||
@@ -106,8 +117,10 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d21076
|
||||
// Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+ this.connections.getYZ(player).values().forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent
|
||||
+ this.connections.clearYZ(player); // Lophine - concurrent
|
||||
+ this.connections.getYZ(player).forEach((entry) -> {
|
||||
+ entry.getValue().disconnect();
|
||||
+ this.connections.remove(player, entry.getKey(), entry.getValue());
|
||||
+ }); // Lophine - concurrent
|
||||
+ this.untrackWaypoint((WaypointTransmitter)player);
|
||||
+ this.players.remove(player);
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
@@ -116,28 +129,49 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..73b69b0d93c17ab8bd3a7c0226d21076
|
||||
public void breakAllConnections() {
|
||||
- this.connections.values().forEach(WaypointTransmitter.Connection::disconnect);
|
||||
- this.connections.clear();
|
||||
+ this.connections.getAllZ().forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent
|
||||
+ java.util.List<WaypointTransmitter.Connection> map = this.connections.getAllZ(); // Lophine - concurrent
|
||||
+ if (!map.isEmpty()) map.forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent
|
||||
+ this.connections.clearAll(); // Lophine - concurrent
|
||||
}
|
||||
|
||||
public void remakeConnections(WaypointTransmitter waypoint) {
|
||||
@@ -86,7 +125,8 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
this.connections.put(player, waypoint, connection);
|
||||
@@ -83,13 +131,19 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
if (player != waypoint) {
|
||||
if (isLocatorBarEnabledFor(player)) {
|
||||
waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection -> {
|
||||
- this.connections.put(player, waypoint, connection);
|
||||
+ this.connections.putOrUpdate(player, waypoint, connection);
|
||||
connection.connect();
|
||||
}, () -> {
|
||||
- WaypointTransmitter.Connection connection = this.connections.remove(player, waypoint);
|
||||
+ WaypointTransmitter.Connection connection = this.connections.getZ(player, waypoint); // Lophine - concurrent
|
||||
+ this.connections.remove(player, waypoint, connection); // Lophine - concurrent
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
@@ -106,7 +146,8 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
this.connections.put(player, waypoint, connection1);
|
||||
- if (connection != null) {
|
||||
- connection.disconnect();
|
||||
- }
|
||||
+ // Lophine start - concurrent
|
||||
+ java.util.List<WaypointTransmitter.Connection> c = this.connections.getZ(player, waypoint);
|
||||
+ if (c.isEmpty()) return; // Lophine - concurrent
|
||||
+ c.forEach((connection) -> {
|
||||
+ this.connections.remove(player, waypoint, connection);
|
||||
+ if (connection != null) {
|
||||
+ connection.disconnect();
|
||||
+ }
|
||||
+ });
|
||||
+ // Lophine end - concurrent
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -103,10 +157,12 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
} else {
|
||||
waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection1 -> {
|
||||
connection1.connect();
|
||||
- this.connections.put(player, waypoint, connection1);
|
||||
+ this.connections.putOrUpdate(player, waypoint, connection1);
|
||||
}, () -> {
|
||||
connection.disconnect();
|
||||
- this.connections.remove(player, waypoint);
|
||||
+ WaypointTransmitter.Connection c = this.connections.getZ(player, waypoint); // Lophine - concurrent
|
||||
+ this.connections.remove(player, waypoint, c); // Lophine - concurrent
|
||||
+ java.util.List<WaypointTransmitter.Connection> c = this.connections.getZ(player, waypoint); // Lophine - concurrent
|
||||
+ if (c.isEmpty()) return; // Lophine - concurrent
|
||||
+ c.forEach((connection1) -> this.connections.remove(player, waypoint, connection1)); // Lophine - concurrent
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -5,10 +5,10 @@ Subject: [PATCH] Fix datapack command save function
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 2f4970242c754cfba8ff5656a63af07d9d0a723c..b156b5c635f931a3d4abc0584591f90476d011a6 100644
|
||||
index df5ff1cc7b289c3f52723d4e7b418e79ae6c3082..8f74af03cf0af0960b1016c8304ca0e440969215 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2353,6 +2353,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2358,6 +2358,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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..67f3454e6479abb241a7d94699d4f7bec22da56b 100644
|
||||
index 1cefe9d83788dafc293aeb6d1b5e635211094b2a..e423d5c0614823ce9a8fbd32b672232e5758e3c1 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -334,6 +334,8 @@ public final class RegionizedServer {
|
||||
@@ -336,6 +336,8 @@ public final class RegionizedServer {
|
||||
}
|
||||
// Luminol end - Add a config to enable tick command
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 923aca94520f456a13d4e4eb23e1499b3dbc920f..0ee9e51c5abfd9269bcf0bb29c4b8394b27af02a 100644
|
||||
index 7584ba257d61bf650d83a2316ff012df928d54f3..4d71cc3b643f6f594c90f2f8f9e5b820ebdff080 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2901,7 +2901,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
+1
-1
@@ -23,7 +23,7 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
|
||||
+ // Leaves end - servux
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 0ee9e51c5abfd9269bcf0bb29c4b8394b27af02a..d1a799199a68771ae3130a30a59625587c11b0b0 100644
|
||||
index 4d71cc3b643f6f594c90f2f8f9e5b820ebdff080..7fb095c544294796768ce19c4409416e2848e296 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
+6
-6
@@ -33,7 +33,7 @@ index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..58694e28b3ff85ef038fe2ada2672e6d
|
||||
private DisconnectionDetails disconnectionDetails;
|
||||
private boolean encrypted;
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786e46148b1 100644
|
||||
index 8f74af03cf0af0960b1016c8304ca0e440969215..c33757d3e53a97148c11f601cde0b6127d663f11 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -347,6 +347,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -57,7 +57,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
||||
// Folia start - region threading
|
||||
// halt scheduler
|
||||
// don't wait, we may be on a scheduler thread
|
||||
@@ -1588,7 +1595,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1593,7 +1600,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
|
||||
@@ -66,7 +66,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
||||
this.emptyTicks++;
|
||||
} else {
|
||||
this.emptyTicks = 0;
|
||||
@@ -1912,6 +1919,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1917,6 +1924,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
public void tickConnection() {
|
||||
this.getConnection().tick();
|
||||
@@ -74,7 +74,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
||||
}
|
||||
|
||||
private void synchronizeTime(ServerLevel level) {
|
||||
@@ -2983,6 +2991,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2988,6 +2996,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -511,7 +511,7 @@ index 8e2775e873c92beed6a0e4e8ce1304ab8ca6e8d1..580f114fd99b017403c61e994d0c947d
|
||||
|
||||
public boolean canBypassPlayerLimit(GameProfile profile) {
|
||||
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd13444f4ad 100644
|
||||
index 65a4956ba2f0e38da7ae4f8cd7ed6e4b02c015a9..044ded5ec81905e38efe8812ff6d50259d761385 100644
|
||||
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
@@ -24,6 +24,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
@@ -526,7 +526,7 @@ index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd1
|
||||
this.waypoints.add(waypoint);
|
||||
|
||||
for (ServerPlayer serverPlayer : this.players) {
|
||||
@@ -59,6 +64,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
@@ -63,6 +68,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
// Folia - region threading
|
||||
// Lophine start - unsafe waypoint bar
|
||||
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+1
-1
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index f8bc2679d9eeaa5d179ab70a4cc5c97522bcc674..a536dc4e09b22b69bcdf59871a9cccfcf8129395 100644
|
||||
index 0d906776e10605ecfe7c681dbf313cf25080d2e8..1f44a59e46f86ca055e89631d831a38f4c3e238e 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -754,6 +754,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
+5
-5
@@ -84,10 +84,10 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378
|
||||
players.add(serverPlayer1);
|
||||
if (players.size() >= resultLimit) {
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 81726e5782d25ff35a2bea8820a62786e46148b1..3c94631f468f4ee1b46de9981c17171e5901d745 100644
|
||||
index c33757d3e53a97148c11f601cde0b6127d663f11..c67fed7b35f273a2eb6809897a891988fe30558c 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1800,7 +1800,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1805,7 +1805,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
private ServerStatus.Players buildPlayerStatus() {
|
||||
@@ -96,7 +96,7 @@ index 81726e5782d25ff35a2bea8820a62786e46148b1..3c94631f468f4ee1b46de9981c17171e
|
||||
int maxPlayers = this.getMaxPlayers();
|
||||
if (this.hidesOnlinePlayers()) {
|
||||
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||
@@ -2001,7 +2001,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2006,7 +2006,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
@@ -105,7 +105,7 @@ index 81726e5782d25ff35a2bea8820a62786e46148b1..3c94631f468f4ee1b46de9981c17171e
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2415,7 +2415,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2420,7 +2420,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||
// Paper start - we don't need to save everything, just advancements
|
||||
// this.getPlayerList().saveAll();
|
||||
@@ -114,7 +114,7 @@ index 81726e5782d25ff35a2bea8820a62786e46148b1..3c94631f468f4ee1b46de9981c17171e
|
||||
player.getAdvancements().save();
|
||||
}
|
||||
// Paper end - we don't need to save everything, just advancements
|
||||
@@ -2554,7 +2554,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2559,7 +2559,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (!playerList.isUsingWhitelist()) return; // Paper - whitelist not enabled
|
||||
UserWhiteList whiteList = playerList.getWhiteList();
|
||||
|
||||
+4
-4
@@ -33,10 +33,10 @@ index 7280ca2250ade4166a1a883b205bbc89f4e00d1a..06268ac3420fc03a798a20bb617ba89a
|
||||
throw makeReportedException(var4, packet, processor);
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 3c94631f468f4ee1b46de9981c17171e5901d745..f7a2a19c0832ca90536d09de23f4ec9a7d4a1521 100644
|
||||
index c67fed7b35f273a2eb6809897a891988fe30558c..1f1e23d9cd73e3ada89367a080de445a18823d7f 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1878,8 +1878,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1883,8 +1883,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
try {
|
||||
profiler.startTimer(serverLevel.tickTimerId); try { // Folia - profiler
|
||||
serverLevel.tick(hasTimeLeft, region); // Folia - region threading
|
||||
@@ -55,7 +55,7 @@ index 3c94631f468f4ee1b46de9981c17171e5901d745..f7a2a19c0832ca90536d09de23f4ec9a
|
||||
serverLevel.fillReportDetails(crashReport);
|
||||
throw new ReportedException(crashReport);
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index a4ee2bcdb31f889c7edbbc422636782c0d5d0af6..42bf4f0430a232a10cffb47d0d33f586afdc2a4d 100644
|
||||
index c58b88f09e6f08d178fcb17a13dd790c3cb62aae..c0ba36849da0983117901f0cd04b2c785df0010b 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -840,7 +840,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -168,7 +168,7 @@ index 9b9842462b210b0407279ee8a8e9ccecf3ead005..1057f3bd32ff4c8f93f09251341c2439
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a536dc4e09b22b69bcdf59871a9cccfcf8129395..a557045888b153bb046a25d276d811b9146a7874 100644
|
||||
index 1f44a59e46f86ca055e89631d831a38f4c3e238e..39c075173b77b5197af5d4ad3fe235ea0d2df756 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -378,7 +378,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
+1
-1
@@ -765,7 +765,7 @@ index e9749b66239d7562ecf22002bfbaa95df197050f..6e3841ed012eee16dcaa61f70edfc1d8
|
||||
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a557045888b153bb046a25d276d811b9146a7874..568427a952a24012c17f64f62b6545a9d89c8c8a 100644
|
||||
index 39c075173b77b5197af5d4ad3fe235ea0d2df756..b8a2ac505d121b46c33db2fbf4d02c5bc60c6c0f 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -401,20 +401,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
+1
-1
@@ -46,7 +46,7 @@ index 8f112f382190d606a87f38da8bcdf8dd5f31d1c5..f27915e43df8e627000cda1cb213a953
|
||||
// CraftBukkit start
|
||||
if (bukkitState != null) {
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 568427a952a24012c17f64f62b6545a9d89c8c8a..49a740bf17b2bed8010e347747b170b69ac26929 100644
|
||||
index b8a2ac505d121b46c33db2fbf4d02c5bc60c6c0f..7a8ceb00eb5845a1d5011a518f63a9cabf131f3c 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -971,12 +971,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 17 Dec 2025 00:20:57 +0800
|
||||
Subject: [PATCH] Add null check in RegionizedWorldData >> conections
|
||||
|
||||
some of our function patches will crash because of get null in conn.getPlayer(), then when we process player.chunkPosition() will get NPE, so we need to fix it.
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 7cc41630a39c1e29840d70eee78473d06b7c11cd..d0ab09a77953c1ccd309637ba80c47a37114f082 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -230,14 +230,17 @@ public final class RegionizedWorldData {
|
||||
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift)).itemEntityMovementTrackerMap.put(key, tracker);
|
||||
}
|
||||
// Luminol end
|
||||
+ Set<Connection> cons = new java.util.HashSet<>(from.connections.size()); // Lophine - save all connections we have processed in connection process
|
||||
// connections
|
||||
for (final Connection conn : from.connections) {
|
||||
final ServerPlayer player = conn.getPlayer();
|
||||
+ if (player == null) continue; // Lophine - skip null player connections
|
||||
final ChunkPos pos = player.chunkPosition();
|
||||
// Note: It is impossible for an entity in the world to _not_ be in an entity chunk, which means
|
||||
// the chunk holder must _exist_, and so the region section exists.
|
||||
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
|
||||
.connections.add(conn);
|
||||
+ cons.add(conn); // Lophine - save all connections we have processed in connection process
|
||||
}
|
||||
// entities
|
||||
for (final ServerPlayer player : from.localPlayers) {
|
||||
@@ -247,6 +250,13 @@ public final class RegionizedWorldData {
|
||||
final RegionizedWorldData into = regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift));
|
||||
into.localPlayers.add(player);
|
||||
into.nearbyPlayers.addPlayer(player);
|
||||
+ // Lophine start - we need to process the connection if player's connection is not processed, if connection.player is null, next tick will clean up it
|
||||
+ final Connection conn = player.connection.connection;
|
||||
+ if (!cons.contains(conn)) {
|
||||
+ regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
|
||||
+ .connections.add(conn);
|
||||
+ }
|
||||
+ // Lophine end
|
||||
}
|
||||
for (final Entity entity : from.allEntities) {
|
||||
final ChunkPos pos = entity.chunkPosition();
|
||||
@@ -577,6 +587,7 @@ public final class RegionizedWorldData {
|
||||
private static void cleanUpConnection(final Connection conn) {
|
||||
// note: ALL connections HERE have a player
|
||||
final ServerPlayer player = conn.getPlayer();
|
||||
+ if (player == null) return; // Lophine - skip null player connections
|
||||
// now that the connection is removed, we can allow this region to die
|
||||
player.level().moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(
|
||||
ServerGamePacketListenerImpl.DISCONNECT_TICKET, player.connection.disconnectPos,
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 13 Jan 2026 21:04:59 +0800
|
||||
Subject: [PATCH] Add removed check before all checks start in addEffect
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 205e2648569b7c18f488aa4d3d9ec944bb1babf4..c6ee14f14e051b30012e608b84a055ff2468850d 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1174,6 +1174,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||
// Paper end - Don't fire sync event during generation
|
||||
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
|
||||
+ if (this.isRemoved()) return false; // Lophine - shouldn't be possible to add effects to removed entity
|
||||
if (!this.hasNullCallback()) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add effects to entities asynchronously"); // Folia - region threading
|
||||
if (this.isTickingEffects) {
|
||||
this.effectsToProcess.add(new ProcessableEffect(effectInstance, cause));
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mrhua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 3 Jan 2026 10:42:39 +0800
|
||||
Subject: [PATCH] Luminol - 1.21.11: Sync dragon part when teleportation or
|
||||
firstly created
|
||||
|
||||
A simple fix of https://github.com/PaperMC/Folia/issues/371
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
index e3a49083e75116622bd95fb17533730a6fb36752..545697d9c081a270ff47b332baee68372c0dd67d 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
@@ -96,6 +96,7 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()), enderpearl.getId()); // Folia - region threading
|
||||
}
|
||||
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||
entity.registerScheduler(); // Paper - optimise Folia entity scheduler
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index f63252c580c313ccf89304866cfc6503f4b26052..f0ddf0bf462a316f82f4babac17af6860b6ba143 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4325,6 +4325,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
Entity copy = this.getType().create(destination, EntitySpawnReason.DIMENSION_TRAVEL);
|
||||
copy.restoreFrom(this);
|
||||
copy.transform(pos, yaw, pitch, velocity);
|
||||
+ if (copy instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||
if (toSameWorld) copy.notifyLithiumTrackerIfNeeded();// Luminol - region threading for sleeping block entity
|
||||
// vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here
|
||||
// for example, clearing of inventory after switching dimensions
|
||||
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index 84d215a498d9bf6f1232bf4af5a4a98d3ba9b131..2aa57b995d9fcfbd335655ef383314ce11d93707 100644
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -1003,4 +1003,12 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
return flag ? i : 0;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Luminol start - Sync dragon part when teleportation or firstly created
|
||||
+ public void syncDragonPartsAfterTeleportTransform() {
|
||||
+ for (EnderDragonPart part : this.subEntities) {
|
||||
+ this.tickPart(part, 0.0, 0.0, 0.0); // offset -> 0.0
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
@@ -79,7 +79,7 @@ index 7883b7973570b5f275a03c6aac4d3b4392e7fa6e..18d066c605f8027d9b1170b64ef1428f
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 679529d94c16960527e5d76adb61c7e536f55d3e..503e11640bd2b6f7c854747723d26fe9cd67f490 100644
|
||||
index 7334422a6e0e7faec675cf038ccbca0e284f61b5..7fee749197b6c6a8890567a7a7819f45b290012b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -338,7 +338,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
|
||||
+11
-1
@@ -22,11 +22,21 @@ public class CommandConfig implements IConfigModule {
|
||||
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
|
||||
@ConfigInfo(name = "waypoint_command_enabled", comments =
|
||||
"""
|
||||
Allow to use waypoint command""")
|
||||
Allow to use waypoint command and locator bar""")
|
||||
public static boolean waypoint = false;
|
||||
|
||||
@ConfigInfo(name = "scoreboard_command_enabled", comments =
|
||||
"""
|
||||
Allow to use scoreboard command""")
|
||||
public static boolean scoreboard = false;
|
||||
|
||||
@ConfigInfo(name = "enabled", directory = {"save_all_command"}, comments =
|
||||
"""
|
||||
Allow to use save-all command""")
|
||||
public static boolean saveAll = false;
|
||||
|
||||
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"}, comments =
|
||||
"""
|
||||
Log all process of save-all command to console""")
|
||||
public static boolean logAllProcess = false;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package fun.bm.lophine.config.modules.function;
|
||||
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import fun.bm.lophine.utils.RandomProfilePool;
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "replay-api")
|
||||
public class ReplayAPIConfig implements IConfigModule {
|
||||
@HotReloadUnsupported
|
||||
@ConfigInfo(name = "enable-cache")
|
||||
public static boolean enableCache = true;
|
||||
|
||||
@HotReloadUnsupported
|
||||
@ConfigInfo(name = "cache-photographer-time", comments = """
|
||||
Time to cache photographer profile(in seconds)""")
|
||||
public static int cachePhotographerTime = 3600;
|
||||
|
||||
@HotReloadUnsupported
|
||||
@ConfigInfo(name = "cache-photographer-size", comments = """
|
||||
Maximum size of cache photographer profile""")
|
||||
public static int cachePhotographerSize = 100;
|
||||
|
||||
@Override
|
||||
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
|
||||
RandomProfilePool.init();
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package fun.bm.lophine.config.modules.optimizations;
|
||||
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "waypoint")
|
||||
public class WayPointOptimizedTableConfig implements IConfigModule {
|
||||
@HotReloadUnsupported
|
||||
@ConfigInfo(name = "optimizedTable", comments = """
|
||||
Should use optimized table instead of normal concurrent table for waypoints.
|
||||
May improve performance when there are many waypoints and players.
|
||||
When enabled, more memory is needed to store data.""")
|
||||
public static boolean optimizedTable = false;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class EntitiesCounterUtil {
|
||||
synchronized (globalLoadedEntities) {
|
||||
globalLoadedEntities.get(level).remove(uniqueId);
|
||||
}
|
||||
synchronized (mobsMap) {
|
||||
synchronized (mobsAreaMap) {
|
||||
mobsAreaMap.get(level).remove(uniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package fun.bm.lophine.utils;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import fun.bm.lophine.config.modules.function.ReplayAPIConfig;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RandomProfilePool {
|
||||
private static int lastUsedId = 0;
|
||||
private static final Object lock = new Object();
|
||||
private static Cache<Integer, GameProfile> cache;
|
||||
private static final Object lockCache = new Object();
|
||||
|
||||
public static void init() {
|
||||
if (ReplayAPIConfig.enableCache) {
|
||||
cache = CacheBuilder.newBuilder()
|
||||
.maximumSize(ReplayAPIConfig.cachePhotographerSize)
|
||||
.expireAfterWrite(ReplayAPIConfig.cachePhotographerTime, TimeUnit.SECONDS)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static GameProfile getRandomProfile(String id) {
|
||||
if (ReplayAPIConfig.enableCache) {
|
||||
synchronized (lockCache) {
|
||||
for (Map.Entry<Integer, GameProfile> entry : cache.asMap().entrySet()) {
|
||||
int key0 = entry.getKey();
|
||||
cache.invalidate(key0);
|
||||
GameProfile gp = entry.getValue();
|
||||
GameProfile ret = new GameProfile(gp.getId(), id);
|
||||
gp.getProperties().asMap().forEach(
|
||||
(key, values) ->
|
||||
values.forEach((value) ->
|
||||
ret.getProperties().put(key, value)
|
||||
)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new GameProfile(UUID.randomUUID(), id);
|
||||
}
|
||||
|
||||
public static void putProfile(GameProfile profile) {
|
||||
if (ReplayAPIConfig.enableCache) {
|
||||
synchronized (lockCache) {
|
||||
cache.put(getNextId(), profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNextId() {
|
||||
synchronized (lock) {
|
||||
int newId = lastUsedId + 1;
|
||||
while (cache.getIfPresent(newId) != null) {
|
||||
newId++;
|
||||
}
|
||||
lastUsedId = newId;
|
||||
return newId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package fun.bm.lophine.utils;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import fun.bm.lophine.config.modules.experiment.CommandConfig;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.commands.SaveAllCommand;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SaveAllUtil {
|
||||
private static final long TIMEOUT = 1000 * 30; // 30 seconds
|
||||
public static final Object lock = new Object();
|
||||
public static volatile long lastSaveAllTime = 0;
|
||||
private static volatile Pair<CommandSourceStack, Boolean> currentSaveAll = null;
|
||||
private static volatile int regionCount = 0;
|
||||
private static final AtomicInteger savedRegionCount = new AtomicInteger(0);
|
||||
private static final AtomicBoolean withError = new AtomicBoolean(false);
|
||||
|
||||
public static void preSaveAll(CommandSourceStack source, boolean flush) {
|
||||
synchronized (lock) {
|
||||
if (isSaving()) {
|
||||
source.sendFailure(Component.literal("Server is already in saving! Please wait..."));
|
||||
} else {
|
||||
source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
currentSaveAll = Pair.of(source, flush);
|
||||
// we need to count how many regions we need to save
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
for (ServerLevel world : source.getServer().getAllLevels()) {
|
||||
world.regioniser.computeForAllRegions(unused -> {
|
||||
count.getAndIncrement();
|
||||
});
|
||||
}
|
||||
regionCount = count.get();
|
||||
savedRegionCount.set(0);
|
||||
withError.set(false);
|
||||
lastSaveAllTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void postRegionSave(io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
|
||||
Pair<CommandSourceStack, Boolean> currentSaveAll = SaveAllUtil.currentSaveAll;
|
||||
synchronized (lock) {
|
||||
if (lastSaveAllTime < region.lastSavedTime) return; // already saved
|
||||
}
|
||||
try {
|
||||
region.world.moonrise$getChunkTaskScheduler().chunkHolderManager.saveAllChunksRegionised(currentSaveAll.getSecond(), false, CommandConfig.logAllProcess, false, true, false);
|
||||
currentSaveAll.getFirst().getServer().getPlayerList().saveAll();
|
||||
MinecraftServer.LOGGER.info("Saved chunks in region around chunk {} in world '{}'", region.region.getCenterChunk(), region.region.regioniser.world.getWorld().getName());
|
||||
} catch (final Throwable thr) {
|
||||
CommandSyntaxException error = SaveAllCommand.getErrorFailed().create();
|
||||
currentSaveAll.getFirst().sendFailure(Component.literal(error.getMessage()));
|
||||
MinecraftServer.LOGGER.error(error.getMessage(), thr);
|
||||
withError.set(true);
|
||||
}
|
||||
region.lastSavedTime = System.currentTimeMillis();
|
||||
int saved;
|
||||
synchronized (savedRegionCount) {
|
||||
saved = savedRegionCount.incrementAndGet();
|
||||
}
|
||||
if (saved >= regionCount) {
|
||||
if (withError.get()) {
|
||||
currentSaveAll.getFirst().sendFailure(Component.literal("At least one region failed to save!"));
|
||||
} else if (saved == regionCount) {
|
||||
currentSaveAll.getFirst().sendSuccess(() -> Component.translatable("commands.save.success"), true);
|
||||
SaveAllUtil.currentSaveAll = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkTimeout() {
|
||||
Pair<CommandSourceStack, Boolean> currentSaveAll = SaveAllUtil.currentSaveAll;
|
||||
if (!isSaving()) return;
|
||||
if (System.currentTimeMillis() - lastSaveAllTime > TIMEOUT) {
|
||||
currentSaveAll.getFirst().sendFailure(Component.literal("At least one region save data timeout!"));
|
||||
currentSaveAll.getFirst().sendFailure(Component.literal("Regions need to save expect is " + regionCount + ", but only " + savedRegionCount.get() + " saved!"));
|
||||
SaveAllUtil.currentSaveAll = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSaving() {
|
||||
synchronized (lock) {
|
||||
return currentSaveAll != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package fun.bm.lophine.utils.concurrent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractConcurrentTable<X, Y, Z> {
|
||||
public abstract void putOrUpdate(X x, Y y, Z z);
|
||||
|
||||
public abstract void put(X x, Y y, Z z);
|
||||
|
||||
public abstract void remove(X x, Y y, Z z);
|
||||
|
||||
public abstract List<Z> getZ(X x, Y y);
|
||||
|
||||
public abstract List<Y> getY(X x, Z z);
|
||||
|
||||
public abstract List<X> getX(Y y, Z z);
|
||||
|
||||
public abstract List<Map.Entry<X, Y>> getXY(Z z);
|
||||
|
||||
public abstract List<Map.Entry<Y, Z>> getYZ(X x);
|
||||
|
||||
public abstract List<Map.Entry<X, Z>> getXZ(Y y);
|
||||
|
||||
public abstract List<X> getAllX();
|
||||
|
||||
public abstract List<Y> getAllY();
|
||||
|
||||
public abstract List<Z> getAllZ();
|
||||
|
||||
public abstract void clearXY(Z z);
|
||||
|
||||
public abstract void clearYZ(X x);
|
||||
|
||||
public abstract void clearXZ(Y y);
|
||||
|
||||
public abstract void clearAll();
|
||||
}
|
||||
@@ -1,116 +1,150 @@
|
||||
package fun.bm.lophine.utils.concurrent;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ConcurrentTable<X, Y, Z> {
|
||||
ConcurrentLinkedDeque<TableEntry<X, Y, Z>> data = new ConcurrentLinkedDeque<>();
|
||||
public class ConcurrentTable<X, Y, Z> extends AbstractConcurrentTable<X, Y, Z> {
|
||||
protected final ConcurrentLinkedDeque<TableEntry<X, Y, Z>> data = new ConcurrentLinkedDeque<>();
|
||||
|
||||
@Override
|
||||
public void putOrUpdate(X x, Y y, Z z) {
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getX().equals(x) && entry.getY().equals(y)) {
|
||||
entry.setZ(z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.put(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(X x, Y y, Z z) {
|
||||
data.add(new TableEntry<>(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(X x, Y y, Z z) {
|
||||
data.removeIf(entry -> entry.getX().equals(x) && entry.getY().equals(y) && entry.getZ().equals(z));
|
||||
}
|
||||
|
||||
public Z getZ(X x, Y y) {
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getX().equals(x) && entry.getY().equals(y)) {
|
||||
return entry.getZ();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
public List<Z> getZ(X x, Y y) {
|
||||
return filterAndCollect(
|
||||
entry -> entry.getX().equals(x) && entry.getY().equals(y),
|
||||
TableEntry::getZ
|
||||
);
|
||||
}
|
||||
|
||||
public Y getY(X x, Z z) {
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getX().equals(x) && entry.getZ().equals(z)) {
|
||||
return entry.getY();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
public List<Y> getY(X x, Z z) {
|
||||
return filterAndCollect(
|
||||
entry -> entry.getX().equals(x) && entry.getZ().equals(z),
|
||||
TableEntry::getY
|
||||
);
|
||||
}
|
||||
|
||||
public X getX(Y y, Z z) {
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getY().equals(y) && entry.getZ().equals(z)) {
|
||||
return entry.getX();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
public List<X> getX(Y y, Z z) {
|
||||
return filterAndCollect(
|
||||
entry -> entry.getY().equals(y) && entry.getZ().equals(z),
|
||||
TableEntry::getX
|
||||
);
|
||||
}
|
||||
|
||||
public Map<X, Y> getXY(Z z) {
|
||||
HashMap<X, Y> map = new HashMap<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getZ().equals(z)) {
|
||||
map.put(entry.getX(), entry.getY());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
@Override
|
||||
public List<Map.Entry<X, Y>> getXY(Z z) {
|
||||
return filterAndMap(
|
||||
entry -> entry.getZ().equals(z),
|
||||
TableEntry::getX,
|
||||
TableEntry::getY
|
||||
);
|
||||
}
|
||||
|
||||
public Map<Y, Z> getYZ(X x) {
|
||||
HashMap<Y, Z> map = new HashMap<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getX().equals(x)) {
|
||||
map.put(entry.getY(), entry.getZ());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
@Override
|
||||
public List<Map.Entry<Y, Z>> getYZ(X x) {
|
||||
return filterAndMap(
|
||||
entry -> entry.getX().equals(x),
|
||||
TableEntry::getY,
|
||||
TableEntry::getZ
|
||||
);
|
||||
}
|
||||
|
||||
public Map<X, Z> getXZ(Y y) {
|
||||
HashMap<X, Z> map = new HashMap<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getY().equals(y)) {
|
||||
map.put(entry.getX(), entry.getZ());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
@Override
|
||||
public List<Map.Entry<X, Z>> getXZ(Y y) {
|
||||
return filterAndMap(
|
||||
entry -> entry.getY().equals(y),
|
||||
TableEntry::getX,
|
||||
TableEntry::getZ
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<X> getAllX() {
|
||||
List<X> xList = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
xList.add(entry.getX());
|
||||
}
|
||||
return xList;
|
||||
return collectAll(TableEntry::getX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Y> getAllY() {
|
||||
List<Y> yList = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
yList.add(entry.getY());
|
||||
}
|
||||
return yList;
|
||||
return collectAll(TableEntry::getY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Z> getAllZ() {
|
||||
List<Z> zList = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
zList.add(entry.getZ());
|
||||
}
|
||||
return zList;
|
||||
return collectAll(TableEntry::getZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearXY(Z z) {
|
||||
data.removeIf(entry -> entry.getZ().equals(z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearYZ(X x) {
|
||||
data.removeIf(entry -> entry.getX().equals(x));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearXZ(Y y) {
|
||||
data.removeIf(entry -> entry.getY().equals(y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAll() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
private <T> List<T> filterAndCollect(Predicate<TableEntry<X, Y, Z>> filter,
|
||||
java.util.function.Function<TableEntry<X, Y, Z>, T> mapper) {
|
||||
List<T> result = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (filter.test(entry)) {
|
||||
result.add(mapper.apply(entry));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private <K, V> List<Map.Entry<K, V>> filterAndMap(Predicate<TableEntry<X, Y, Z>> filter,
|
||||
java.util.function.Function<TableEntry<X, Y, Z>, K> keyMapper,
|
||||
java.util.function.Function<TableEntry<X, Y, Z>, V> valueMapper) {
|
||||
List<Map.Entry<K, V>> list = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (filter.test(entry)) {
|
||||
list.add(new AbstractMap.SimpleEntry<>(keyMapper.apply(entry), valueMapper.apply(entry)));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private <T> List<T> collectAll(java.util.function.Function<TableEntry<X, Y, Z>, T> mapper) {
|
||||
List<T> result = new ArrayList<>();
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
result.add(mapper.apply(entry));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
package fun.bm.lophine.utils.concurrent;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OptimizedConcurrentTable<X, Y, Z> extends ConcurrentTable<X, Y, Z> {
|
||||
private final ConcurrentHashMap<X, ConcurrentHashMap<Y, Set<Z>>> xyIndex = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Y, ConcurrentHashMap<Z, Set<X>>> yzIndex = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Z, ConcurrentHashMap<X, Set<Y>>> zxIndex = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void putOrUpdate(X x, Y y, Z z) {
|
||||
boolean updated = false;
|
||||
|
||||
for (TableEntry<X, Y, Z> entry : data) {
|
||||
if (entry.getX().equals(x) && entry.getY().equals(y)) {
|
||||
removeFromIndex(xyIndex, entry.getX(), entry.getY(), entry.getZ());
|
||||
removeFromIndex(yzIndex, entry.getY(), entry.getZ(), entry.getX());
|
||||
removeFromIndex(zxIndex, entry.getZ(), entry.getX(), entry.getY());
|
||||
|
||||
entry.setZ(z);
|
||||
|
||||
putData(x, y, z);
|
||||
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!updated) {
|
||||
this.put(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private void putData(X x, Y y, Z z) {
|
||||
xyIndex.computeIfAbsent(x, k -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(y, k -> ConcurrentHashMap.newKeySet()).add(z);
|
||||
yzIndex.computeIfAbsent(y, k -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(z, k -> ConcurrentHashMap.newKeySet()).add(x);
|
||||
zxIndex.computeIfAbsent(z, k -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(x, k -> ConcurrentHashMap.newKeySet()).add(y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void put(X x, Y y, Z z) {
|
||||
super.put(x, y, z);
|
||||
putData(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(X x, Y y, Z z) {
|
||||
super.remove(x, y, z);
|
||||
removeFromIndex(xyIndex, x, y, z);
|
||||
removeFromIndex(yzIndex, y, z, x);
|
||||
removeFromIndex(zxIndex, z, x, y);
|
||||
}
|
||||
|
||||
private <K, V, T> void removeFromIndex(ConcurrentHashMap<K, ConcurrentHashMap<V, Set<T>>> index,
|
||||
K key1, V key2, T value) {
|
||||
index.computeIfPresent(key1, (k, map) -> {
|
||||
map.computeIfPresent(key2, (k2, set) -> {
|
||||
set.remove(value);
|
||||
return set.isEmpty() ? null : set;
|
||||
});
|
||||
return map.isEmpty() ? null : map;
|
||||
});
|
||||
}
|
||||
|
||||
public void removeAll(Predicate<TableEntry<X, Y, Z>> predicate) {
|
||||
data.removeIf(entry -> {
|
||||
boolean shouldRemove = predicate.test(entry);
|
||||
if (shouldRemove) {
|
||||
removeFromIndex(xyIndex, entry.getX(), entry.getY(), entry.getZ());
|
||||
removeFromIndex(yzIndex, entry.getY(), entry.getZ(), entry.getX());
|
||||
removeFromIndex(zxIndex, entry.getZ(), entry.getX(), entry.getY());
|
||||
}
|
||||
return shouldRemove;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean putIfAbsent(X x, Y y, Z z) {
|
||||
if (data.stream().anyMatch(entry ->
|
||||
Objects.equals(entry.getX(), x) &&
|
||||
Objects.equals(entry.getY(), y) &&
|
||||
Objects.equals(entry.getZ(), z))) {
|
||||
return false;
|
||||
}
|
||||
put(x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Z> getZ(X x, Y y) {
|
||||
Set<Z> result = xyIndex.getOrDefault(x, new ConcurrentHashMap<>()).get(y);
|
||||
return result != null ? new ArrayList<>(result) : new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Y> getY(X x, Z z) {
|
||||
Set<Y> result = zxIndex.getOrDefault(z, new ConcurrentHashMap<>()).get(x);
|
||||
return result != null ? new ArrayList<>(result) : new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<X> getX(Y y, Z z) {
|
||||
Set<X> result = yzIndex.getOrDefault(y, new ConcurrentHashMap<>()).get(z);
|
||||
return result != null ? new ArrayList<>(result) : new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map.Entry<X, Y>> getXY(Z z) {
|
||||
return buildDataFromIndex(zxIndex.get(z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map.Entry<Y, Z>> getYZ(X x) {
|
||||
return buildDataFromIndex(xyIndex.get(x));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map.Entry<X, Z>> getXZ(Y y) {
|
||||
return reverseDataFromIndex(yzIndex.get(y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<X> getAllX() {
|
||||
Set<X> resultSet = new HashSet<>(xyIndex.keySet());
|
||||
return new ArrayList<>(resultSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Y> getAllY() {
|
||||
Set<Y> resultSet = new HashSet<>(yzIndex.keySet());
|
||||
return new ArrayList<>(resultSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Z> getAllZ() {
|
||||
Set<Z> resultSet = new HashSet<>(zxIndex.keySet());
|
||||
return new ArrayList<>(resultSet);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearXY(Z z) {
|
||||
super.clearXY(z);
|
||||
zxIndex.remove(z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearYZ(X x) {
|
||||
super.clearYZ(x);
|
||||
xyIndex.remove(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearXZ(Y y) {
|
||||
super.clearXZ(y);
|
||||
yzIndex.remove(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAll() {
|
||||
super.clearAll();
|
||||
xyIndex.clear();
|
||||
yzIndex.clear();
|
||||
zxIndex.clear();
|
||||
}
|
||||
|
||||
|
||||
private <K, V, R> List<R> buildEntriesFromIndex(ConcurrentHashMap<K, Set<V>> indexMap,
|
||||
BiFunction<K, V, R> entryCreator) {
|
||||
List<R> result = new ArrayList<>();
|
||||
if (indexMap != null) {
|
||||
for (Map.Entry<K, Set<V>> entry : indexMap.entrySet()) {
|
||||
K key = entry.getKey();
|
||||
Set<V> valueSet = entry.getValue();
|
||||
if (valueSet != null && !valueSet.isEmpty()) {
|
||||
for (V value : valueSet) {
|
||||
result.add(entryCreator.apply(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private <K, V> List<Map.Entry<K, V>> buildDataFromIndex(ConcurrentHashMap<K, Set<V>> indexMap) {
|
||||
return buildEntriesFromIndex(indexMap, AbstractMap.SimpleEntry::new);
|
||||
}
|
||||
|
||||
private <K, V> List<Map.Entry<V, K>> reverseDataFromIndex(ConcurrentHashMap<K, Set<V>> indexMap) {
|
||||
return buildEntriesFromIndex(indexMap, (key, value) -> new AbstractMap.SimpleEntry<>(value, key));
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package fun.bm.lophine.utils.concurrent;
|
||||
public class TableEntry<X, Y, Z> {
|
||||
private final X x;
|
||||
private final Y y;
|
||||
private final Z z;
|
||||
private Z z;
|
||||
|
||||
public TableEntry(X x, Y y, Z z) {
|
||||
this.x = x;
|
||||
@@ -22,4 +22,8 @@ public class TableEntry<X, Y, Z> {
|
||||
public Z getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(Z z) {
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.leavesmc.leaves.replay;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import fun.bm.lophine.utils.RandomProfilePool;
|
||||
import io.papermc.paper.threadedregions.RegionizedServer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ClientInformation;
|
||||
@@ -70,7 +71,7 @@ public class ServerPhotographer extends ServerPlayer {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
|
||||
ServerLevel world = ((CraftWorld) state.loc.getWorld()).getHandle();
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), state.id);
|
||||
GameProfile profile = RandomProfilePool.getRandomProfile(state.id); // Lophine - add cache
|
||||
|
||||
ServerPhotographer photographer = new ServerPhotographer(server, world, profile);
|
||||
photographer.absSnapTo(state.loc.x(), state.loc.y(), state.loc.z(), state.loc.getYaw(), state.loc.getPitch());
|
||||
@@ -165,6 +166,7 @@ public class ServerPhotographer extends ServerPlayer {
|
||||
photographers.remove(this);
|
||||
|
||||
MinecraftServer.getServer().getPlayerList().removePhotographer(this);
|
||||
RandomProfilePool.putProfile(this.gameProfile); // Lophine - add cache
|
||||
if (!recorder.isSaved()) {
|
||||
CompletableFuture<Void> future = recorder.saveRecording(saveFile, save);
|
||||
if (!async) {
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
####################################################################################################################
|
||||
|
||||
version: "1.0"
|
||||
linter: jetbrains/qodana-jvm:2025.2
|
||||
linter: jetbrains/qodana-jvm-community:latest
|
||||
profile:
|
||||
name: qodana.recommended
|
||||
include:
|
||||
- name: CheckDependencyLicenses
|
||||
- name: CheckDependencyLicenses
|
||||
|
||||
Reference in New Issue
Block a user