Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d818e30
Initial experimental work on Folia support
SirYwell Mar 7, 2023
8ebc938
Improve block tracing performance
SirYwell Mar 8, 2023
b2aadf9
Throw exception if player is retired to ensure task always finishes
SirYwell Mar 9, 2023
ec343a9
Add folia support
TheMeinerLP Mar 30, 2023
a6e5950
Set paperweight to local dev build
TheMeinerLP Apr 2, 2023
9095a74
Add a local folia dev build
TheMeinerLP Apr 2, 2023
7bb5815
Add run folia task
TheMeinerLP Apr 2, 2023
2c042b5
Port taskmanager for folia
TheMeinerLP Apr 2, 2023
abc39c3
Fix tasks manager
TheMeinerLP Apr 2, 2023
db4808b
Fix port for folia
TheMeinerLP Apr 2, 2023
4f84e36
Remove maven local
TheMeinerLP Apr 2, 2023
84e7dd4
Build back to paper adapter
TheMeinerLP Apr 2, 2023
07ae60d
Add special adapter load for folia
TheMeinerLP Apr 2, 2023
6c9bf0a
Add folia adapter
TheMeinerLP Apr 2, 2023
5dd8903
Fix package for classes
TheMeinerLP Apr 2, 2023
bd59522
Fix package for classes
TheMeinerLP Apr 2, 2023
240bf81
Improve search for folia adapter
TheMeinerLP Apr 2, 2023
48d50ae
Fix shading of folia adapters
TheMeinerLP Apr 2, 2023
4bee821
Add runFolia with snapshot version of run paper
TheMeinerLP Apr 2, 2023
e763695
Fix regen command
TheMeinerLP Apr 2, 2023
b3a56de
Fix UnsupportedOperationException on disable
TheMeinerLP Apr 2, 2023
7c3c91f
Use new method to check of is running on "main thread"
TheMeinerLP Apr 3, 2023
034aa10
Implement dirty workaround for get data from right ticking region
TheMeinerLP Apr 3, 2023
ba778fe
Implement dirty workaround for get data from right ticking region
TheMeinerLP Apr 3, 2023
b605445
Implement dirty workaround for get data from right ticking region
TheMeinerLP Apr 3, 2023
434a58f
Improve scheduling for chunk data of regen
TheMeinerLP Apr 3, 2023
6c0b7ac
Fix compass tool
TheMeinerLP Apr 3, 2023
eb34a4f
Merge remote-tracking branch 'fork-https/feature/folia-support' into …
TheMeinerLP Apr 5, 2023
e2cb7ea
Merge branch 'main' into feature/folia-support
TheMeinerLP May 31, 2023
f1bb12c
Fix duplicated import
TheMeinerLP May 31, 2023
4892913
Add folia check
TheMeinerLP Jun 6, 2023
fbcf77f
Implements method handles for folia
TheMeinerLP Jun 6, 2023
403c69e
Implements method handles for folia
TheMeinerLP Jun 6, 2023
cbae64f
Implements method handles for folia
TheMeinerLP Jun 6, 2023
ebe53a8
Add folia workaround
TheMeinerLP Jun 18, 2023
fe45611
Fix reflections and casting
TheMeinerLP Jun 18, 2023
8038618
Fix access to world data
TheMeinerLP Jun 18, 2023
f8c9d21
Remove folia search path
TheMeinerLP Jun 18, 2023
cee3b6e
Remove duplicated code
TheMeinerLP Jun 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import org.ajoberstar.grgit.Grgit
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED
import xyz.jpenilla.runpaper.task.RunServer
import java.net.URI
import java.time.format.DateTimeFormatter
import xyz.jpenilla.runpaper.task.RunServer

plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
Expand Down Expand Up @@ -102,6 +102,15 @@ tasks {
.toTypedArray())

}
register<RunServer>("runFolia") {
downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project))
minecraftVersion("1.19.4")
group = "run paper"
runDirectory.set(file("run-folia"))
jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true")
pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
.toTypedArray())
}
}

nexusPublishing {
Expand Down
10 changes: 9 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ include("worldedit-libs")
listOf("legacy", "1_17_1", "1_18_2", "1_19", "1_19_3","1_19_4").forEach {
include("worldedit-bukkit:adapters:adapter-$it")
}

listOf("bukkit", "core", "cli").forEach {
include("worldedit-libs:$it")
include("worldedit-$it")
Expand All @@ -21,5 +20,14 @@ dependencyResolutionManagement {
}
}
}
pluginManagement {
repositories {
gradlePluginPortal()
maven {
name = "jmp repository"
url = uri("https://repo.jpenilla.xyz/snapshots")
}
}
}

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
Expand Down Expand Up @@ -266,7 +266,7 @@ public void run(Object value) {
}
}
};
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
Expand All @@ -220,7 +220,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
Expand Down Expand Up @@ -266,7 +266,7 @@ public void run(Object value) {
}
}
};
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
Expand All @@ -248,7 +248,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
Expand Down Expand Up @@ -266,7 +266,7 @@ public void run(Object value) {
}
}
};
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
Expand All @@ -281,7 +281,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
Expand Down Expand Up @@ -259,7 +260,13 @@ public BlockState getBlock(Location location) {
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
LevelChunk chunk;
if (Fawe.isTickThread()) {
// TODO check if is owned by this thread, else synchronize
chunk = handle.getChunk(x >> 4, z >> 4);
} else {
chunk = TaskManager.taskManager().syncAt(() -> handle.getChunk(x >> 4, z >> 4), BukkitAdapter.adapt(location));
}
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd
this.level = level;
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
// TODO
this.lastTick = new AtomicInteger(0);
}

private Level getLevel() {
Expand Down Expand Up @@ -95,7 +96,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
Expand Down Expand Up @@ -266,7 +267,7 @@ public void run(Object value) {
}
}
};
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.mojang.datafixers.util.Either;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
Expand Down Expand Up @@ -263,7 +267,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
Expand All @@ -278,7 +282,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
if (Fawe.isTickThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
Expand Down Expand Up @@ -352,13 +356,19 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole
);
}
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
});
}, toLocation(nmsWorld, coordIntPair));
}

private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
}

public static Location toLocation(ServerLevel serverLevel, ChunkPos chunkPos) {
final World adapt = BukkitAdapter.adapt(serverLevel.getWorld());
final Vector3 pos = Vector3.at(chunkPos.getMinBlockX(), 0, chunkPos.getMinBlockZ());
return new Location(adapt, pos);
}

/*
NMS conversion
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.FoliaSupport;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.Location;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongIterator;
Expand Down Expand Up @@ -101,39 +103,53 @@ private void fixLighting(LongSet chunks, Runnable andThen) {
while (iterator.hasNext()) {
coords.add(new ChunkPos(iterator.nextLong()));
}
if (FoliaSupport.isFolia()) {
relightRegion(andThen, coords);
return;
}
TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE
))
);
}
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v ->
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads
TaskManager.taskManager().async(andThen);
}
)
);
relightRegion(andThen, coords);
});
}

private void relightRegion(Runnable andThen, Set<ChunkPos> coords) {
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE
))
);
}
Location location = toLocation(coords.iterator().next());
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAcceptAsync(v ->
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.taskManager().task(() -> postProcessChunks(coords), location);
// call callback on our own threads
TaskManager.taskManager().async(andThen);
}
),
task -> TaskManager.taskManager().task(task, location)
);
}

private Location toLocation(ChunkPos chunkPos) {
return PaperweightPlatformAdapter.toLocation(this.serverLevel, chunkPos);
}

private void invokeRelight(
Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
private final Field chunkProviderExecutorField;
private final Watchdog watchdog;

private final Boolean folia;

// ------------------------------------------------------------------------
// Code that may break between versions of Minecraft
// ------------------------------------------------------------------------
Expand All @@ -185,6 +187,16 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException {
throw new UnsupportedClassVersionError("Not 1.19.4!");
}

boolean isFolia = false;
try {
// Assume API is present
Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler");
isFolia = true;
} catch (Exception unused) {

}
this.folia = isFolia;

serverWorldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true);

Expand Down Expand Up @@ -221,6 +233,10 @@ public PaperweightAdapter() throws NoSuchFieldException, NoSuchMethodException {
}
}

public Boolean isFolia() {
return folia;
}

@Override
public DataFixer getDataFixer() {
return PaperweightDataConverters.INSTANCE;
Expand Down
Loading