-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
2,555 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,40 @@ | ||
# ForkTest - A Paper fork, using paperweight | ||
|
||
This is an example project, showcasing how to setup a fork of Paper (or any other fork using paperweight), using paperweight. | ||
|
||
The files of most interest are | ||
- build.gradle.kts | ||
- settings.gradle.kts | ||
- gradle.properties | ||
|
||
When updating upstream, be sure to keep the dependencies noted in `build.gradle.kts` in sync with upstream. | ||
It's also a good idea to use the same version of the Gradle wrapper as upstream. | ||
|
||
## Tasks | ||
|
||
``` | ||
Paperweight tasks | ||
----------------- | ||
applyApiPatches | ||
applyPatches | ||
applyServerPatches | ||
cleanCache - Delete the project setup cache and task outputs. | ||
createMojmapBundlerJar - Build a runnable bundler jar | ||
createMojmapPaperclipJar - Build a runnable paperclip jar | ||
createReobfBundlerJar - Build a runnable bundler jar | ||
createReobfPaperclipJar - Build a runnable paperclip jar | ||
generateDevelopmentBundle | ||
rebuildApiPatches | ||
rebuildPatches | ||
rebuildServerPatches | ||
reobfJar - Re-obfuscate the built jar to obf mappings | ||
runDev - Spin up a non-relocated Mojang-mapped test server | ||
runReobf - Spin up a test server from the reobfJar output jar | ||
runShadow - Spin up a test server from the shadowJar archiveFile | ||
``` | ||
|
||
## Branches | ||
|
||
Each branch of this project represents an example: | ||
|
||
- [`main` is the standard example](https://github.com/PaperMC/paperweight-examples/tree/main) | ||
- [`submodules` shows how paperweight can be applied on a fork using the more traditional git submodule system](https://github.com/PaperMC/paperweight-examples/tree/submodules) | ||
- [`mojangapi` shows how a fork could patch arbitrary non-git directories (such as `Paper-MojangAPI`)](https://github.com/PaperMC/paperweight-examples/tree/mojangapi) | ||
- [`submodules-mojang` shows the same as `mojangapi`, but on the git submodules setup from `submodules`](https://github.com/PaperMC/paperweight-examples/tree/submodules-mojangapi) | ||
![chiyogami](https://user-images.githubusercontent.com/34712108/135766838-98102b74-0990-4408-af3d-d576edb0b8fb.png) | ||
|
||
Chiyogamiは [Paper](https://github.com/PaperMC/Paper) をフォークしたものであり、Spigotプラグインを動作させつつマルチスレッド実行を可能とするMinecraftサーバーソフトです。 | ||
|
||
[![Support Server](https://img.shields.io/discord/893173646728757268.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge)](https://discord.com/invite/KKQNAPsFR6) | ||
|
||
> [Download](https://github.com/bea4dev/Chiyogami/releases) | ||
Other versions | ||
------ | ||
* [1.18.2](https://github.com/bea4dev/Chiyogami/tree/ver/1.18.2) | ||
* [1.19.2](https://github.com/bea4dev/Chiyogami/tree/ver/1.19.2) | ||
|
||
Notes | ||
------ | ||
- [x] このサーバーは開発段階であるため十分なテストがされていません | ||
- [x] このサーバーを実行する前には必ずワールドデータ等のバックアップをしてください | ||
- [x] issue等のフィードバックを歓迎します | ||
|
||
API | ||
------ | ||
APIは未公開です | ||
|
||
How to build | ||
------ | ||
|
||
ビルドを実行するには、git, jdk17が必要です。 | ||
|
||
1. リポジトリを [ダウンロード](https://codeload.github.com/bea4dev/Chiyogami/zip/refs/heads/ver/1.20.1) or clone して解凍します。 | ||
2. 解凍したフォルダ内でWindowsの場合はgit-bash、linux or Macの場合はターミナルを開き```./gradlew applyPatches```を実行したあと```./gradlew createReobfBundlerJar```を実行します | ||
3. ```build/libs```内にjarファイルが生成されていれば成功です | ||
|
||
For developer | ||
------ | ||
|
||
このサーバーはワールドにそれぞれ専用のスレッドを割り当て、半ば楽観的に同期を取りつつ動作します。 | ||
|
||
コマンドやスケジューラー系統の処理はマルチスレッド化した中には含まれていないので互換性を維持し易くなっています。 | ||
|
||
イベントの発火処理にはデフォルトで排他制御が設けられますが、ワールド間での順序関係は保証されないため注意が必要です。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: bea4dev <bea0224@outlook.jp> | ||
Date: Mon, 12 Jun 2023 17:49:25 +0900 | ||
Subject: [PATCH] chiyogami-init-commit-0 | ||
|
||
|
||
diff --git a/src/main/java/world/chiyogami/thread/ConcurrentTaskHandler.java b/src/main/java/world/chiyogami/thread/ConcurrentTaskHandler.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..eb918bd7e4f689f85abd4b8d30f49f71a95ed0ad | ||
--- /dev/null | ||
+++ b/src/main/java/world/chiyogami/thread/ConcurrentTaskHandler.java | ||
@@ -0,0 +1,52 @@ | ||
+package world.chiyogami.thread; | ||
+ | ||
+import org.bukkit.World; | ||
+import java.util.function.Supplier; | ||
+ | ||
+/** | ||
+ * Task utility class for safe operation on worlds from other threads. | ||
+ */ | ||
+public abstract class ConcurrentTaskHandler { | ||
+ | ||
+ protected static ConcurrentTaskHandler INSTANCE = null; | ||
+ | ||
+ /** | ||
+ * Performs tasks to the target world in a thread-safe and non-delayed manner. | ||
+ * <p> | ||
+ * When accessing from a thread other than the main thread. Typically, a latency of 50 ms or less is incurred. | ||
+ * <p> | ||
+ * <b>This method only guarantees thread-safety for operations on worlds, | ||
+ * not for global variables or methods (e.g. Bukkit.createInventory();).</b> | ||
+ * | ||
+ * @param targetWorld The world in which the task is to be performed. | ||
+ * @param task Supplier task. | ||
+ * @return Result of supplier. | ||
+ */ | ||
+ public static <T> T runConcurrentTaskForWorld(World targetWorld, Supplier<T> task) { | ||
+ return INSTANCE.runConcurrentTaskForWorldImpl(targetWorld, task); | ||
+ } | ||
+ | ||
+ /** | ||
+ * Performs tasks to the target world in a thread-safe and non-delayed manner. | ||
+ * <p> | ||
+ * When accessing from a thread other than the main thread. Typically, a latency of 50 ms or less is incurred. | ||
+ * <p> | ||
+ * <b>This method only guarantees thread-safety for operations on worlds, | ||
+ * not for global variables or methods (e.g. Bukkit.createInventory();).</b> | ||
+ * | ||
+ * @param targetWorld The world in which the task is to be performed. | ||
+ * @param runnable Runnable task. | ||
+ */ | ||
+ public static void runConcurrentTaskForWorld(World targetWorld, Runnable runnable) { | ||
+ INSTANCE.runConcurrentTaskForWorldImpl(targetWorld, () -> { | ||
+ runnable.run(); | ||
+ return null; | ||
+ }); | ||
+ } | ||
+ | ||
+ | ||
+ protected ConcurrentTaskHandler(){INSTANCE = this;} | ||
+ | ||
+ protected abstract <T> T runConcurrentTaskForWorldImpl(World targetWorld, Supplier<T> supplier); | ||
+ | ||
+} | ||
diff --git a/src/main/java/world/chiyogami/thread/WorldThreadLockHandler.java b/src/main/java/world/chiyogami/thread/WorldThreadLockHandler.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..b3c5d30fe0fe3457cb8c533906373a66e00a7508 | ||
--- /dev/null | ||
+++ b/src/main/java/world/chiyogami/thread/WorldThreadLockHandler.java | ||
@@ -0,0 +1,14 @@ | ||
+package world.chiyogami.thread; | ||
+ | ||
+abstract class WorldThreadLockHandler { | ||
+ | ||
+ public static WorldThreadLockHandler INSTANCE; | ||
+ | ||
+ | ||
+ protected WorldThreadLockHandler() {INSTANCE = this;} | ||
+ | ||
+ public abstract void lock(WorldThreadSafeLock worldThreadSafeLock); | ||
+ | ||
+ public abstract void unlock(WorldThreadSafeLock worldThreadSafeLock); | ||
+ | ||
+} | ||
diff --git a/src/main/java/world/chiyogami/thread/WorldThreadRunnable.java b/src/main/java/world/chiyogami/thread/WorldThreadRunnable.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..1694e1e7cb34b47a7165910672d04054a310b9ab | ||
--- /dev/null | ||
+++ b/src/main/java/world/chiyogami/thread/WorldThreadRunnable.java | ||
@@ -0,0 +1,53 @@ | ||
+package world.chiyogami.thread; | ||
+ | ||
+import org.bukkit.World; | ||
+import org.jetbrains.annotations.NotNull; | ||
+ | ||
+public abstract class WorldThreadRunnable implements Runnable { | ||
+ | ||
+ private World world = null; | ||
+ | ||
+ private long period = 0; | ||
+ | ||
+ private long delay = 0; | ||
+ | ||
+ private boolean canceled = false; | ||
+ | ||
+ private boolean scheduled = false; | ||
+ | ||
+ public World getWorld() {return world;} | ||
+ | ||
+ public long getPeriod() {return period;} | ||
+ | ||
+ public long getDelay() {return delay;} | ||
+ | ||
+ public synchronized boolean isCanceled() {return canceled;} | ||
+ | ||
+ public synchronized void cancel() {this.canceled = true;} | ||
+ | ||
+ public synchronized void runTask(@NotNull World world) { | ||
+ checkScheduled(); | ||
+ this.world = world; | ||
+ scheduled = true; | ||
+ world.scheduleTask(this); | ||
+ } | ||
+ | ||
+ public synchronized void runTaskLater(@NotNull World world, long delay) { | ||
+ checkScheduled(); | ||
+ this.world = world; | ||
+ this.delay = delay; | ||
+ scheduled = true; | ||
+ world.scheduleTask(this, delay); | ||
+ } | ||
+ | ||
+ public synchronized void runTaskTimer(@NotNull World world, long delay, long period) { | ||
+ checkScheduled(); | ||
+ this.world = world; | ||
+ this.delay = delay; | ||
+ this.period = period; | ||
+ scheduled = true; | ||
+ world.scheduleTask(this, delay, period); | ||
+ } | ||
+ | ||
+ private void checkScheduled() {if (scheduled) throw new IllegalStateException("This task is already scheduled.");} | ||
+} | ||
diff --git a/src/main/java/world/chiyogami/thread/WorldThreadSafeLock.java b/src/main/java/world/chiyogami/thread/WorldThreadSafeLock.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..f6874f7bc6ac933453230307176eaafb6ff67fd0 | ||
--- /dev/null | ||
+++ b/src/main/java/world/chiyogami/thread/WorldThreadSafeLock.java | ||
@@ -0,0 +1,45 @@ | ||
+package world.chiyogami.thread; | ||
+ | ||
+import java.util.concurrent.TimeUnit; | ||
+import java.util.concurrent.locks.ReentrantLock; | ||
+ | ||
+/** | ||
+ * ReentrantLock for acquiring locks while avoiding deadlocks in the world thread. | ||
+ */ | ||
+public class WorldThreadSafeLock extends ReentrantLock { | ||
+ | ||
+ public WorldThreadSafeLock(boolean fair) { | ||
+ super(fair); | ||
+ } | ||
+ | ||
+ @Override | ||
+ public void lock() { | ||
+ WorldThreadLockHandler.INSTANCE.lock(this); | ||
+ super.lock(); | ||
+ } | ||
+ | ||
+ @Override | ||
+ public void unlock() { | ||
+ super.unlock(); | ||
+ WorldThreadLockHandler.INSTANCE.unlock(this); | ||
+ } | ||
+ | ||
+ @Override | ||
+ public boolean tryLock() { | ||
+ boolean already = super.tryLock(); | ||
+ if (already) { | ||
+ WorldThreadLockHandler.INSTANCE.lock(this); | ||
+ } | ||
+ return already; | ||
+ } | ||
+ | ||
+ @Override | ||
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { | ||
+ boolean already = super.tryLock(timeout, unit); | ||
+ if (already) { | ||
+ WorldThreadLockHandler.INSTANCE.lock(this); | ||
+ } | ||
+ return already; | ||
+ } | ||
+ | ||
+} |
Oops, something went wrong.