mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
Update changes from ver/1.21.4 branch
This commit is contained in:
12
README.md
12
README.md
@@ -123,7 +123,7 @@ If these excellent projects hadn't existed, Leaf wouldn't have become great.
|
||||
</details>
|
||||
|
||||
## 🔥 Special Thanks
|
||||
<a href="https://cloud.swordsman.com.cn/"><img src="public/image/JiankeServer.jpg" alt="Jianke Cloud Host" align="left" hspace="8"></a>
|
||||
[](https://cloud.swordsman.com.cn/?i8ab42c) \
|
||||
cloud of swordsman | 剑客云
|
||||
|
||||
If you want to find a cheaper, high performance, stable, lower latency host, then cloud of swordsman is a good choice! Registers and purchases in [here](https://cloud.swordsman.com.cn/?i8ab42c).
|
||||
@@ -131,7 +131,15 @@ If you want to find a cheaper, high performance, stable, lower latency host, the
|
||||
如果你想找一个低价高性能、低延迟的云服务商,剑客云是个不错的选择!你可以在 [这里](https://cloud.swordsman.com.cn/?i8ab42c) 注册。
|
||||
|
||||
---
|
||||

|
||||
[](https://www.rainyun.com/NzE2NTc1_) \
|
||||
RainYun | 雨云
|
||||
|
||||
Global multi-line routing with cloud storage. Refund available within 7 days. Reliable uptime and expert support. RainYun — stable, cost-effective, and ready for fast cloud deployment. Visit [RainYun]([雨云](https://www.rainyun.com/NzE2NTc1_))
|
||||
|
||||
国际多线路选择,配套云存储 — 购买服务后七天内不满意可以申请退订,强大的技术支持团队和高在线率客服。雨云云服务器,用稳定和性价比,助力您快速上云。点击前往 [雨云](https://www.rainyun.com/NzE2NTc1_)。
|
||||
|
||||
---
|
||||
 \
|
||||
|
||||
YourKit supports open source projects with innovative and intelligent tools
|
||||
for monitoring and profiling Java and .NET applications.
|
||||
|
||||
@@ -3,76 +3,91 @@ From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Sat, 3 Feb 2024 18:45:53 -0500
|
||||
Subject: [PATCH] Configurable LibraryLoader maven repos
|
||||
|
||||
TODO - Dreeam: Support multi maven repos for lib downloading.
|
||||
|
||||
Add JVM flag `-DLeaf.library-download-repo=link` to choose library download repo link.
|
||||
e.g. `-DLeaf.library-download-repo=https://maven.aliyun.com/repository/public`
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
index 107705db2d82b7c191e5e625ec888e0bc3b03831..77a58fc7c173b1724d44b0eeaf23b4a1b22b5fcb 100644
|
||||
index 107705db2d82b7c191e5e625ec888e0bc3b03831..d7dc6ff0b372de04c956cae6fc27d2679b88e0f7 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
@@ -105,7 +105,7 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
* dependencies from
|
||||
@@ -3,9 +3,11 @@ package io.papermc.paper.plugin.loader.library.impl;
|
||||
import io.papermc.paper.plugin.loader.library.ClassPathLibrary;
|
||||
import io.papermc.paper.plugin.loader.library.LibraryLoadingException;
|
||||
import io.papermc.paper.plugin.loader.library.LibraryStore;
|
||||
+
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
+
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
@@ -57,6 +59,13 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
private final List<RemoteRepository> repositories = new ArrayList<>();
|
||||
private final List<Dependency> dependencies = new ArrayList<>();
|
||||
|
||||
+ // Leaf start - Configurable LibraryLoader maven repos
|
||||
+ @org.jspecify.annotations.Nullable
|
||||
+ public static final RemoteRepository MAVEN_CENTRAL_MIRROR_REPO = getCentralMirrorRepo();
|
||||
+ private static final String[] MAVEN_CENTRAL_URLS = new String[]{
|
||||
+ };
|
||||
+ // Leaf end - Configurable LibraryLoader maven repos
|
||||
+
|
||||
/**
|
||||
* Creates a new maven library resolver instance.
|
||||
* <p>
|
||||
@@ -102,9 +111,24 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
* repository.
|
||||
*
|
||||
* @param remoteRepository the configuration that defines the maven repository this library resolver should fetch
|
||||
- * dependencies from
|
||||
+ * dependencies from
|
||||
*/
|
||||
public void addRepository(final RemoteRepository remoteRepository) {
|
||||
- this.repositories.add(remoteRepository);
|
||||
+ this.repositories.add(org.dreeam.leaf.plugin.loader.MavenCentralMirror.getCentralRepo(remoteRepository)); // Leaf - Configurable LibraryLoader maven repos
|
||||
+ // Leaf start - Configurable LibraryLoader maven repos
|
||||
+ for (String url : MAVEN_CENTRAL_URLS) {
|
||||
+ if (remoteRepository.getUrl().startsWith(url)) {
|
||||
+ RemoteRepository mirrorRepo = MAVEN_CENTRAL_MIRROR_REPO;
|
||||
+ if (mirrorRepo != null) {
|
||||
+ this.repositories.add(mirrorRepo);
|
||||
+ return;
|
||||
+ }
|
||||
+ LOGGER.warn(
|
||||
+ "Use of Maven Central as a CDN is against the Maven Central Terms of Service. Use MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR instead.",
|
||||
+ new RuntimeException("Plugin used Maven Central for library resolution")
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end - Configurable LibraryLoader maven repos
|
||||
this.repositories.add(remoteRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,4 +154,15 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
store.addLibrary(file.toPath());
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaf start - Configurable LibraryLoader maven repos
|
||||
+ @org.jspecify.annotations.Nullable
|
||||
+ private static RemoteRepository getCentralMirrorRepo() {
|
||||
+ String mirrorAddr = System.getProperty("Leaf.library-download-repo");
|
||||
+ if (mirrorAddr != null) {
|
||||
+ new RemoteRepository.Builder("central", "default", mirrorAddr).build();
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Leaf end - Configurable LibraryLoader maven repos
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
index cfe41c0a67c8d729b6bd23b0cfa32db3c9db9f74..9f167a9cb4a93a79b8ed709b61214ce0138a875d 100644
|
||||
index cfe41c0a67c8d729b6bd23b0cfa32db3c9db9f74..05d3b793bf9cb320774f9f488a3b78bedab6a9d4 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
@@ -74,7 +74,19 @@ public class LibraryLoader {
|
||||
session.setSystemProperties(System.getProperties());
|
||||
session.setReadOnly();
|
||||
@@ -47,6 +47,8 @@ public class LibraryLoader {
|
||||
public static java.util.function.BiFunction<URL[], ClassLoader, URLClassLoader> LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries
|
||||
public static java.util.function.Function<List<java.nio.file.Path>, List<java.nio.file.Path>> REMAPPER; // Paper - remap libraries
|
||||
|
||||
- this.repositories = repository.newResolutionRepositories(session, Arrays.asList(new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2").build()));
|
||||
+ // Leaf start - Configurable LibraryLoader maven repos
|
||||
+ this.repositories = repository.newResolutionRepositories(
|
||||
+ session,
|
||||
+ List.of(org.dreeam.leaf.plugin.loader.MavenCentralMirror.getCentralRepo("https://repo.maven.apache.org/maven2"))
|
||||
+ );
|
||||
+ /* // Dreeam TODO
|
||||
+ this.repositories = repository.newResolutionRepositories(session, List.of(
|
||||
+ new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2").build(),
|
||||
+ new RemoteRepository.Builder("aliyun", "default", "https://maven.aliyun.com/repository/public").build(),
|
||||
+ new RemoteRepository.Builder("tencentclound", "default", "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/").build(),
|
||||
+ new RemoteRepository.Builder("huaweicloud", "default", "https://repo.huaweicloud.com/repository/maven/").build()
|
||||
+ ));*/
|
||||
+ // Leaf end - Configurable LibraryLoader maven repos
|
||||
}
|
||||
+ if (io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver.MAVEN_CENTRAL_MIRROR_REPO != null) return List.of(io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver.MAVEN_CENTRAL_MIRROR_REPO); // Leaf - Configurable LibraryLoader maven repos
|
||||
+
|
||||
public LibraryLoader(@NotNull Logger logger) {
|
||||
this.logger = logger;
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/org/dreeam/leaf/plugin/loader/MavenCentralMirror.java b/src/main/java/org/dreeam/leaf/plugin/loader/MavenCentralMirror.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..95534cb6d771a0fe288e7c843c41b0036bdc7095
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/plugin/loader/MavenCentralMirror.java
|
||||
@@ -0,0 +1,24 @@
|
||||
+package org.dreeam.leaf.plugin.loader;
|
||||
+
|
||||
+import org.eclipse.aether.repository.RemoteRepository;
|
||||
+
|
||||
+public class MavenCentralMirror {
|
||||
+
|
||||
+ public static final String MAVEN_CENTRAL_MIRROR_REPO = System.getProperty("Leaf.library-download-repo");
|
||||
+
|
||||
+ public static RemoteRepository getCentralRepo(RemoteRepository repo) {
|
||||
+ if (MAVEN_CENTRAL_MIRROR_REPO != null && repo.getUrl().contains("repo.maven.apache.org/maven2")) {
|
||||
+ repo = new RemoteRepository.Builder("central", "default", MAVEN_CENTRAL_MIRROR_REPO).build();
|
||||
+ }
|
||||
+
|
||||
+ return repo;
|
||||
+ }
|
||||
+
|
||||
+ public static RemoteRepository getCentralRepo(String repo) {
|
||||
+ if (MAVEN_CENTRAL_MIRROR_REPO != null) {
|
||||
+ repo = MAVEN_CENTRAL_MIRROR_REPO;
|
||||
+ }
|
||||
+
|
||||
+ return new RemoteRepository.Builder("central", "default", repo).build();
|
||||
+ }
|
||||
+}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Wed, 18 Jun 2025 10:47:21 -0700
|
||||
Subject: [PATCH] Paper: Avoid and discourage use of Maven Central as a CDN
|
||||
|
||||
Removed since Leaf 1.21.6, added in Paper
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/PaperMC/Paper
|
||||
|
||||
https://github.com/PaperMC/Paper/commit/62b7f86dae659deb2fc450285452d7c1439f92dc
|
||||
|
||||
Default LibraryLoader to Google's Maven Central mirror, add MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR, and warn on use of Maven Central with MavenLibraryResolver
|
||||
|
||||
https://www.sonatype.com/blog/maven-central-and-the-tragedy-of-the-commons
|
||||
https://www.sonatype.com/blog/beyond-ips-addressing-organizational-overconsumption-in-maven-central
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
index 107705db2d82b7c191e5e625ec888e0bc3b03831..ebb52c2c8d5fe8ca25513aadae8168180a3d426e 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
|
||||
@@ -41,7 +41,7 @@ import org.slf4j.LoggerFactory;
|
||||
* MavenLibraryResolver resolver = new MavenLibraryResolver();
|
||||
* resolver.addDependency(new Dependency(new DefaultArtifact("org.jooq:jooq:3.17.7"), null));
|
||||
* resolver.addRepository(new RemoteRepository.Builder(
|
||||
- * "central", "default", "https://repo1.maven.org/maven2/"
|
||||
+ * "central", "default", MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR // Paper - Avoid and discourage use of Maven Central as a CDN
|
||||
* ).build());
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -50,6 +50,24 @@ import org.slf4j.LoggerFactory;
|
||||
@NullMarked
|
||||
public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
|
||||
+ // Paper start - Avoid and discourage use of Maven Central as a CDN
|
||||
+ /**
|
||||
+ * The default Maven Central mirror, configurable through the {@code PAPER_DEFAULT_CENTRAL_REPOSITORY} environment
|
||||
+ * variable. Use this instead of Maven Central directly when you do not have your own mirror, as using
|
||||
+ * Maven Central as a CDN is against the Maven Central Terms of Service, and you will cause users to hit
|
||||
+ * rate limits.
|
||||
+ *
|
||||
+ * <p>This repository is also used by the legacy {@link org.bukkit.plugin.java.LibraryLoader}.</p>
|
||||
+ */
|
||||
+ public static final String MAVEN_CENTRAL_DEFAULT_MIRROR = getDefaultMavenCentralMirror();
|
||||
+ private static final List<String> MAVEN_CENTRAL_URLS = List.of(
|
||||
+ "https://repo1.maven.org/maven2",
|
||||
+ "http://repo1.maven.org/maven2",
|
||||
+ "https://repo.maven.apache.org/maven2",
|
||||
+ "http://repo.maven.apache.org/maven2"
|
||||
+ );
|
||||
+ // Paper end - Avoid and discourage use of Maven Central as a CDN
|
||||
+
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("MavenLibraryResolver");
|
||||
|
||||
private final RepositorySystem repository;
|
||||
@@ -105,6 +123,14 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
* dependencies from
|
||||
*/
|
||||
public void addRepository(final RemoteRepository remoteRepository) {
|
||||
+ // Paper start - Avoid and discourage use of Maven Central as a CDN
|
||||
+ if (MAVEN_CENTRAL_URLS.stream().anyMatch(remoteRepository.getUrl()::startsWith)) {
|
||||
+ LOGGER.warn(
|
||||
+ "Use of Maven Central as a CDN is against the Maven Central Terms of Service. Use MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR instead.",
|
||||
+ new RuntimeException("Plugin used Maven Central for library resolution")
|
||||
+ );
|
||||
+ }
|
||||
+ // Paper end - Avoid and discourage use of Maven Central as a CDN
|
||||
this.repositories.add(remoteRepository);
|
||||
}
|
||||
|
||||
@@ -130,4 +156,17 @@ public class MavenLibraryResolver implements ClassPathLibrary {
|
||||
store.addLibrary(file.toPath());
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start - Avoid and discourage use of Maven Central as a CDN
|
||||
+ private static String getDefaultMavenCentralMirror() {
|
||||
+ String central = System.getenv("PAPER_DEFAULT_CENTRAL_REPOSITORY");
|
||||
+ if (central == null) {
|
||||
+ central = System.getProperty("org.bukkit.plugin.java.LibraryLoader.centralURL");
|
||||
+ }
|
||||
+ if (central == null) {
|
||||
+ central = "https://maven-central.storage-download.googleapis.com/maven2";
|
||||
+ }
|
||||
+ return central;
|
||||
+ }
|
||||
+ // Paper end - Avoid and discourage use of Maven Central as a CDN
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
index 7e4e702845f61703f0741add59f7cfc0afea1543..012ba8ee3d84a7bb09068e42fd1bae8ad221622e 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||
@@ -47,19 +47,11 @@ public class LibraryLoader {
|
||||
public static java.util.function.BiFunction<URL[], ClassLoader, URLClassLoader> LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries
|
||||
public static java.util.function.Function<List<java.nio.file.Path>, List<java.nio.file.Path>> REMAPPER; // Paper - remap libraries
|
||||
|
||||
- // TODO: Consider moving this and adding per plugin support for defining repositories
|
||||
+ // Paper start - Avoid and discourage use of Maven Central as a CDN
|
||||
private static List<RemoteRepository> getRepositories() {
|
||||
- String central = System.getenv("PAPER_DEFAULT_CENTRAL_REPOSITORY");
|
||||
- if (central == null) {
|
||||
- central = System.getProperty("org.bukkit.plugin.java.LibraryLoader.centralURL");
|
||||
- }
|
||||
- if (central == null) {
|
||||
- central = "https://repo.maven.apache.org/maven2";
|
||||
- }
|
||||
-
|
||||
- return Arrays.asList(new RemoteRepository.Builder("central", "default", central).build());
|
||||
-
|
||||
+ return List.of(new RemoteRepository.Builder("central", "default", io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR).build());
|
||||
}
|
||||
+ // Paper end - Avoid and discourage use of Maven Central as a CDN
|
||||
|
||||
public LibraryLoader(@NotNull Logger logger) {
|
||||
this.logger = logger;
|
||||
@@ -87,7 +79,7 @@ public class LibraryLoader {
|
||||
session.setSystemProperties(System.getProperties());
|
||||
session.setReadOnly();
|
||||
|
||||
- this.repositories = repository.newResolutionRepositories(session, getRepositories());
|
||||
+ this.repositories = repository.newResolutionRepositories(session, getRepositories()); // Paper - Avoid and discourage use of Maven Central as a CDN
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1,23 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leymooo <Vjatseslav.Maspanov@gmail.com>
|
||||
Date: Wed, 11 Jun 2025 05:30:39 +0300
|
||||
Subject: [PATCH] PaperPR: Fix excess slot updates / inventory state id desync
|
||||
From: AJ Ferguson <fergusonjva@gmail.com>
|
||||
Date: Mon, 6 Jan 2025 20:31:00 +1100
|
||||
Subject: [PATCH] Paper: Fix excess slot updates
|
||||
|
||||
Removed since Leaf 1.21.6, added in Paper
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||
Original project: https://github.com/PaperMC/Paper
|
||||
Paper pull request: https://github.com/PaperMC/Paper/pull/12654
|
||||
|
||||
Fixes inventory state id desync with high ping causing inventory to be "buggy" (ghost items, items jumping to/from cursor, etc)
|
||||
|
||||
Without patch: https://youtu.be/hOXt3Rpkgtg
|
||||
With patch: https://youtu.be/MtOYD7uieS4
|
||||
|
||||
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/df01cf867a2255024aacf9ac2ff6a56b2ffb7ce5#nms-patches/net/minecraft/world/inventory/Container.patch
|
||||
|
||||
https://discord.com/channels/289587909051416579/555462289851940864/1382165293308182699
|
||||
https://github.com/PaperMC/Paper/commit/e714de636543d61fcd3682705484c8a15f4f3ca6
|
||||
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 9dd3187fd968ab95e9d55b4c8cc74e782cc0f241..c5ede24d00f444d04c835af3a7f0154227492be4 100644
|
||||
index 9dd3187fd968ab95e9d55b4c8cc74e782cc0f241..46c3353a9722cb9c8073cadbad0ced57bab0c390 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -559,7 +559,7 @@ public abstract class AbstractContainerMenu {
|
||||
@@ -25,7 +20,7 @@ index 9dd3187fd968ab95e9d55b4c8cc74e782cc0f241..c5ede24d00f444d04c835af3a7f01542
|
||||
slot.setChanged();
|
||||
// CraftBukkit start - Make sure the client has the right slot contents
|
||||
- if (player instanceof ServerPlayer serverPlayer && slot.getMaxStackSize() != 64) {
|
||||
+ if (player instanceof ServerPlayer serverPlayer && slot.getMaxStackSize() != net.minecraft.world.Container.MAX_STACK) { // Paper - Fix excess slot updates / inventory state id desync
|
||||
+ if (player instanceof ServerPlayer serverPlayer && slot.getMaxStackSize() != Container.MAX_STACK) { // Paper - craftbukkkit - Fix excess slot updates
|
||||
serverPlayer.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem()));
|
||||
// Updating a crafting inventory makes the client reset the result slot, have to send it again
|
||||
if (this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.WORKBENCH || this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.CRAFTING) {
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
Date: Tue, 9 Nov 2077 00:00:00 +0800
|
||||
Subject: [PATCH] Add missing rewrite rules
|
||||
|
||||
TODO: needs to check and fix it.
|
||||
The new added rewriting rules cause incompatible with Nova plugin (The call Registry<*>::freeze in RegistryEventsPatch#transform)
|
||||
It breaks kotlin reflection, makes it can't get all members of Registry class and its parent interfaces.
|
||||
to validate using Nova plugin:
|
||||
```
|
||||
println(net.minecraft.core.Registry::class.members.size)
|
||||
println(net.minecraft.core.Registry::class.java.methods.size)
|
||||
```
|
||||
|
||||
Tracking PR: https://github.com/PaperMC/asm-utils/pull/48
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java b/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java
|
||||
index a3045afbc0cc057e99189b909367b21cf6a9e03f..2831b8b48a12815f8fb7e82327f654e90d1530a3 100644
|
||||
--- a/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java
|
||||
+++ b/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java
|
||||
@@ -22,7 +22,14 @@ public final class ReflectionRemapper {
|
||||
private static final RewriteRuleVisitorFactory VISITOR_FACTORY = RewriteRuleVisitorFactory.create(
|
||||
Opcodes.ASM9,
|
||||
chain -> chain.then(new BaseReflectionRules(PAPER_REFLECTION_HOLDER).rules())
|
||||
- .then(DefineClassRule.create(PAPER_REFLECTION_HOLDER_DESC, true)),
|
||||
+ // Leaf start - Add missing rewrite rules
|
||||
+ .then(
|
||||
+ io.papermc.asm.rules.RewriteRule.forOwnerClass(Class.class, rf -> {
|
||||
+ rf.plainStaticRewrite(java.lang.constant.ClassDesc.of(PAPER_REFLECTION_HOLDER), b -> b
|
||||
+ .match("forName").desc("(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", "(Ljava/lang/Module;Ljava/lang/String;)Ljava/lang/Class;"));
|
||||
+ })
|
||||
+ ).then(DefineClassRule.create(PAPER_REFLECTION_HOLDER_DESC, true)),
|
||||
+ // Leaf end - Add missing rewrite rules
|
||||
ClassInfoProvider.basic()
|
||||
);
|
||||
|
||||
@@ -7,48 +7,78 @@ Original license: MIT
|
||||
Original project: https://github.com/thebrightspark/AsyncLocator
|
||||
|
||||
diff --git a/net/minecraft/server/commands/LocateCommand.java b/net/minecraft/server/commands/LocateCommand.java
|
||||
index a734b2597c3491db35d9660e169f8e8b6320900b..8a79a339757d6ac49713bf6db0fb675d9893fd1b 100644
|
||||
index a734b2597c3491db35d9660e169f8e8b6320900b..5274f09b0abf148aea1c0baa39edbfdac1acc4f5 100644
|
||||
--- a/net/minecraft/server/commands/LocateCommand.java
|
||||
+++ b/net/minecraft/server/commands/LocateCommand.java
|
||||
@@ -106,6 +106,38 @@ public class LocateCommand {
|
||||
@@ -106,6 +106,34 @@ public class LocateCommand {
|
||||
BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
ServerLevel level = source.getLevel();
|
||||
Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
+ // Leaf start - Asynchronous locator
|
||||
+ if (org.dreeam.leaf.config.modules.async.AsyncLocator.enabled) {
|
||||
+ net.minecraft.commands.CommandSource locatorSource = source.source;
|
||||
+ if (locatorSource instanceof net.minecraft.server.level.ServerPlayer || locatorSource instanceof net.minecraft.server.MinecraftServer) {
|
||||
+ BlockPos originPos = BlockPos.containing(source.getPosition());
|
||||
+ BlockPos originPos = BlockPos.containing(source.getPosition());
|
||||
+ org.dreeam.leaf.async.locate.AsyncLocator.locate(source.getLevel(), holderSet, originPos, 100, false)
|
||||
+ .thenOnServerThread(pair -> {
|
||||
+ stopwatch.stop();
|
||||
+ if (pair != null) {
|
||||
+ showLocateResult(
|
||||
+ source,
|
||||
+ structure,
|
||||
+ originPos,
|
||||
+ pair,
|
||||
+ "commands.locate.structure.success",
|
||||
+ false,
|
||||
+ stopwatch.elapsed()
|
||||
+ );
|
||||
+ } else {
|
||||
+ source.sendFailure(
|
||||
+ Component.literal(
|
||||
+ ERROR_STRUCTURE_NOT_FOUND.create(structure.asPrintable()).getMessage()
|
||||
+ )
|
||||
+ );
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ org.dreeam.leaf.async.locate.AsyncLocator.locate(source.getLevel(), holderSet, originPos, 100, false)
|
||||
+ .thenOnServerThread(pair -> {
|
||||
+ stopwatch.stop();
|
||||
+ if (pair != null) {
|
||||
+ showLocateResult(
|
||||
+ source,
|
||||
+ structure,
|
||||
+ originPos,
|
||||
+ pair,
|
||||
+ "commands.locate.structure.success",
|
||||
+ false,
|
||||
+ stopwatch.elapsed()
|
||||
+ );
|
||||
+ } else {
|
||||
+ source.sendFailure(
|
||||
+ Component.literal(
|
||||
+ ERROR_STRUCTURE_NOT_FOUND.create(structure.asPrintable()).getMessage()
|
||||
+ )
|
||||
+ );
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ // Leaf end - Asynchronous locator
|
||||
Pair<BlockPos, Holder<Structure>> pair = level.getChunkSource().getGenerator().findNearestMapStructure(level, holderSet, blockPos, 100, false);
|
||||
stopwatch.stop();
|
||||
if (pair == null) {
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index eaaa66c4d86d4ebda0acf8f1dbe8ecb55aa28285..8f41326fda8c5f9f6926038508be6c6529b051bc 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -852,14 +852,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
|
||||
@Override
|
||||
public boolean pollTask() {
|
||||
+ // Leaf start - Async Locator
|
||||
// Paper start - rewrite chunk system
|
||||
- final ServerChunkCache serverChunkCache = ServerChunkCache.this;
|
||||
- if (serverChunkCache.runDistanceManagerUpdates()) {
|
||||
- return true;
|
||||
+ java.util.function.Supplier<Boolean> supplier = () -> {
|
||||
+ final ServerChunkCache serverChunkCache = ServerChunkCache.this;
|
||||
+ if (serverChunkCache.runDistanceManagerUpdates()) {
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ return super.pollTask() | ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel) serverChunkCache.level).moonrise$getChunkTaskScheduler().executeMainThreadTask();
|
||||
+ }
|
||||
+ };
|
||||
+ if (org.dreeam.leaf.config.modules.async.AsyncLocator.enabled && Thread.currentThread() instanceof org.dreeam.leaf.async.locate.AsyncLocator.AsyncLocatorThread) {
|
||||
+ return MinecraftServer.getServer().scheduleWithResult((java.util.concurrent.CompletableFuture<Boolean> future) -> {
|
||||
+ future.complete(supplier.get());
|
||||
+ }).join();
|
||||
} else {
|
||||
- return super.pollTask() | ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)serverChunkCache.level).moonrise$getChunkTaskScheduler().executeMainThreadTask();
|
||||
+ return supplier.get();
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
+ // Leaf end - Async Locator
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/Dolphin.java b/net/minecraft/world/entity/animal/Dolphin.java
|
||||
index 23696a5e2871ea07f34d4b4f6a20e2896ac3f5bd..c4fda92e078c9ba745b2548ecaaffffff97fb0fd 100644
|
||||
--- a/net/minecraft/world/entity/animal/Dolphin.java
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: hayanesuru <hayanesuru@outlook.jp>
|
||||
Date: Fri, 6 Jun 2025 20:46:10 +0900
|
||||
Subject: [PATCH] optimize random tick
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 46e171ca454253c32e22c0c18587e9a7ba19f331..36e592ff42eba050829f9c4d055c3d49a78ba813 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -633,6 +633,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
} finally {
|
||||
list.clear();
|
||||
}
|
||||
+ this.level.randomTickSystem.tick(this.level); // Leaf - optimize random tick
|
||||
|
||||
this.iterateTickingChunksFaster(); // Paper - chunk tick iteration optimisations
|
||||
if (_boolean) {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 27da552e2542153a58d6177f592cf30d858c41a9..a180612fea46ec9f7dcfe1781e985dd2e98ed513 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1114,6 +1114,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
|
||||
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.simpleRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking
|
||||
|
||||
+ public org.dreeam.leaf.world.RandomTickSystem randomTickSystem = new org.dreeam.leaf.world.RandomTickSystem(); // Leaf - optimize random tick
|
||||
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
|
||||
final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Leaf - Faster random generator - upcasting
|
||||
ChunkPos pos = chunk.getPos();
|
||||
@@ -1129,7 +1130,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
} // Paper - Option to disable ice and snow
|
||||
|
||||
if (randomTickSpeed > 0) {
|
||||
- this.optimiseRandomTick(chunk, randomTickSpeed); // Paper - optimise random ticking
|
||||
+ if (org.dreeam.leaf.config.modules.opt.OptimizeRandomTick.enabled) randomTickSystem.tickChunk(this.simpleRandom, chunk, randomTickSpeed); // Leaf - optimize random tick
|
||||
+ else this.optimiseRandomTick(chunk, randomTickSpeed); // Paper - optimise random ticking // Leaf - optimize random tick
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a3674ddb883eecb255279375a5e2eece7e016c0f..634bf0c15eb63aeb5ff06dd9b43ecbab627b0128 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -152,6 +152,48 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
}
|
||||
// Gale end - Airplane - optimize random calls in chunk ticking - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
|
||||
|
||||
+ // Leaf start - optimize random tick
|
||||
+ private boolean leaf$tickingBlocksDirty = true;
|
||||
+ private int leaf$tickingBlocksCount;
|
||||
+ private int leaf$firstTickingSectionIndex = -1;
|
||||
+ public final int leaf$tickingBlocksCount() {
|
||||
+ if (!leaf$tickingBlocksDirty) {
|
||||
+ return leaf$tickingBlocksCount;
|
||||
+ }
|
||||
+ leaf$tickingBlocksDirty = false;
|
||||
+ int sum = 0;
|
||||
+ leaf$firstTickingSectionIndex = -1;
|
||||
+ for (int i = 0; i < sections.length; i++) {
|
||||
+ LevelChunkSection section = sections[i];
|
||||
+ int size = section.moonrise$getTickingBlockList().size();
|
||||
+ if (size != 0 && leaf$firstTickingSectionIndex == -1) {
|
||||
+ leaf$firstTickingSectionIndex = i;
|
||||
+ }
|
||||
+ sum += size;
|
||||
+ }
|
||||
+ leaf$tickingBlocksCount = sum;
|
||||
+ return sum;
|
||||
+ }
|
||||
+ public final java.util.OptionalLong leaf$getTickingPos(int idx) {
|
||||
+ if (leaf$firstTickingSectionIndex != -1) {
|
||||
+ for (int i = leaf$firstTickingSectionIndex; i < sections.length; i++) {
|
||||
+ LevelChunkSection section = sections[i];
|
||||
+ var l = section.moonrise$getTickingBlockList();
|
||||
+ int size = l.size();
|
||||
+ if (idx < size) {
|
||||
+ short loc = l.getRaw(idx);
|
||||
+ int x = (loc & 15) | (chunkPos.x << 4);
|
||||
+ int y = (loc >>> 8) | ((getMinSectionY() + i) << 4);
|
||||
+ int z = ((loc >>> 4) & 15) | (chunkPos.z << 4);
|
||||
+ return java.util.OptionalLong.of(BlockPos.asLong(x, y, z));
|
||||
+ }
|
||||
+ idx -= size;
|
||||
+ }
|
||||
+ }
|
||||
+ leaf$tickingBlocksDirty = true;
|
||||
+ return java.util.OptionalLong.empty();
|
||||
+ }
|
||||
+ // Leaf end - optimize random tick
|
||||
public LevelChunk(Level level, ChunkPos pos) {
|
||||
this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null);
|
||||
}
|
||||
@@ -416,6 +458,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
if (blockState == state) {
|
||||
return null;
|
||||
} else {
|
||||
+ // Leaf start - optimize random tick
|
||||
+ if (blockState.isRandomlyTicking() != state.isRandomlyTicking()) {
|
||||
+ leaf$tickingBlocksDirty = true;
|
||||
+ }
|
||||
+ // Leaf end - optimize random tick
|
||||
Block block = state.getBlock();
|
||||
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state);
|
||||
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state);
|
||||
@@ -100,7 +100,7 @@ index 4535858701b2bb232b9d2feb2af6551526232ddc..e65c62dbe4c1560ae153e4c4344e9194
|
||||
- // Paper end - detailed watchdog information
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 12cf6dc9bac109a4feeeeede5f3762b20ea582bb..b450ac5e19d42765c739311de1566b7b0c11c88b 100644
|
||||
index 36e592ff42eba050829f9c4d055c3d49a78ba813..b32cb1c85a9f7a7a96a257c4546ee7e21cd91a6d 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -623,8 +623,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -117,10 +117,10 @@ index 12cf6dc9bac109a4feeeeede5f3762b20ea582bb..b450ac5e19d42765c739311de1566b7b
|
||||
|
||||
for (LevelChunk levelChunk : list) {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 117a8ef98c369bf0919e44fe823d6af0758816b5..47357e1d54563e30b4281c410a1ab70ccd672ad0 100644
|
||||
index a180612fea46ec9f7dcfe1781e985dd2e98ed513..7cb8329fc787aa6a9f877afb43dc9cd655cb0e90 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1526,13 +1526,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1518,13 +1518,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Paper end - log detailed entity tick information
|
||||
|
||||
public void tickNonPassenger(Entity entity) {
|
||||
@@ -134,7 +134,7 @@ index 117a8ef98c369bf0919e44fe823d6af0758816b5..47357e1d54563e30b4281c410a1ab70c
|
||||
entity.setOldPosAndRot();
|
||||
entity.tickCount++;
|
||||
entity.totalEntityAge++; // Paper - age-like counter for all entities
|
||||
@@ -1545,13 +1539,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1537,13 +1531,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
for (Entity entity1 : entity.getPassengers()) {
|
||||
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
|
||||
}
|
||||
@@ -149,7 +149,7 @@ index 117a8ef98c369bf0919e44fe823d6af0758816b5..47357e1d54563e30b4281c410a1ab70c
|
||||
|
||||
private void tickPassenger(Entity ridingEntity, Entity passengerEntity, final boolean isActive) { // Paper - EAR 2
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 7573c566aace4b7661c5aed6d96653472bab81bb..84808bf3311067409aad99817d3f1df2c098d83c 100644
|
||||
index fc39af434b59054260d763b994fb50bcf92b4ff3..ddc2a7fbca414b8e3c044cfe7076d2cac182b63e 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1166,16 +1166,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.dreeam.leaf.async.ai;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
@@ -10,85 +9,54 @@ import org.dreeam.leaf.config.modules.async.AsyncTargetFinding;
|
||||
import org.dreeam.leaf.util.queue.SpscIntQueue;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class AsyncGoalExecutor {
|
||||
|
||||
protected static final Logger LOGGER = LogManager.getLogger("Leaf Async Goal");
|
||||
protected final SpscIntQueue queue;
|
||||
protected final SpscIntQueue wake;
|
||||
protected final IntArrayList submit;
|
||||
private final ServerLevel world;
|
||||
private long midTickCount = 0L;
|
||||
|
||||
public AsyncGoalExecutor(AsyncGoalThread thread, ServerLevel world) {
|
||||
public AsyncGoalExecutor(ServerLevel world) {
|
||||
this.world = world;
|
||||
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
||||
this.wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
||||
this.submit = new IntArrayList();
|
||||
}
|
||||
|
||||
boolean wake(int id) {
|
||||
Entity entity = this.world.getEntities().get(id);
|
||||
if (entity == null || entity.isRemoved() || !(entity instanceof Mob mob)) {
|
||||
return false;
|
||||
}
|
||||
mob.goalSelector.ctx.wake();
|
||||
mob.targetSelector.ctx.wake();
|
||||
return true;
|
||||
}
|
||||
|
||||
public final void submit(int entityId) {
|
||||
this.submit.add(entityId);
|
||||
}
|
||||
|
||||
public final void tick() {
|
||||
batchSubmit();
|
||||
boolean wakeAll() {
|
||||
boolean success = false;
|
||||
while (true) {
|
||||
OptionalInt result = this.wake.recv();
|
||||
OptionalInt result = queue.recv();
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
int id = result.getAsInt();
|
||||
if (poll(id) && !this.queue.send(id)) {
|
||||
do {
|
||||
wake(id);
|
||||
} while (poll(id));
|
||||
}
|
||||
success = true;
|
||||
wake(id);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private void batchSubmit() {
|
||||
if (submit.isEmpty()) {
|
||||
public void tickMob(Mob mob) {
|
||||
if (!poll(mob)) {
|
||||
return;
|
||||
}
|
||||
int[] raw = submit.elements();
|
||||
int size = submit.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
int id = raw[i];
|
||||
if (poll(id) && !this.queue.send(id)) {
|
||||
do {
|
||||
wake(id);
|
||||
} while (poll(id));
|
||||
}
|
||||
int entityId = mob.getId();
|
||||
if (!this.queue.send(entityId)) {
|
||||
do {
|
||||
wake(entityId);
|
||||
} while (poll(mob));
|
||||
}
|
||||
this.submit.clear();
|
||||
}
|
||||
|
||||
public final void midTick() {
|
||||
if (AsyncTargetFinding.threshold <= 0L || (midTickCount % AsyncTargetFinding.threshold) == 0L) {
|
||||
batchSubmit();
|
||||
}
|
||||
|
||||
midTickCount += 1;
|
||||
}
|
||||
|
||||
private boolean poll(int id) {
|
||||
private void wake(int id) {
|
||||
Entity entity = this.world.getEntities().get(id);
|
||||
if (entity == null || entity.isRemoved() || !(entity instanceof Mob mob)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
mob.goalSelector.ctx.wake();
|
||||
mob.targetSelector.ctx.wake();
|
||||
}
|
||||
|
||||
private boolean poll(Mob mob) {
|
||||
try {
|
||||
mob.tickingTarget = true;
|
||||
boolean a = mob.targetSelector.poll();
|
||||
@@ -97,8 +65,7 @@ public class AsyncGoalExecutor {
|
||||
return a || b;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Exception while polling", e);
|
||||
// retry
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,26 +22,11 @@ public class AsyncGoalThread extends Thread {
|
||||
while (RUNNING) {
|
||||
boolean retry = false;
|
||||
for (ServerLevel level : server.getAllLevels()) {
|
||||
var exec = level.asyncGoalExecutor;
|
||||
while (true) {
|
||||
OptionalInt result = exec.queue.recv();
|
||||
if (result.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
int id = result.getAsInt();
|
||||
retry = true;
|
||||
if (exec.wake(id)) {
|
||||
while (!exec.wake.send(id)) {
|
||||
Thread.onSpinWait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread.yield();
|
||||
retry |= level.asyncGoalExecutor.wakeAll();
|
||||
}
|
||||
|
||||
if (!retry) {
|
||||
LockSupport.parkNanos(10_000L);
|
||||
LockSupport.parkNanos(1_000_000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.Util;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dreeam.leaf.config.modules.misc.SentryDSN;
|
||||
import org.dreeam.leaf.config.modules.opt.FastBiomeManagerSeedObfuscation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -243,6 +244,7 @@ public class LeafConfig {
|
||||
|
||||
List<String> extraHidden = existing != null ? new ArrayList<>(Arrays.asList(existing.split(","))) : new ArrayList<>();
|
||||
extraHidden.add(SentryDSN.sentryDsnConfigPath); // Hide Sentry DSN key
|
||||
extraHidden.add(FastBiomeManagerSeedObfuscation.seedObfKeyPath); // Hide FastBiomeManagerSeedObfuscation key
|
||||
|
||||
return extraHidden;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ public class AsyncTargetFinding extends ConfigModules {
|
||||
public static boolean searchBlock = true;
|
||||
public static boolean searchEntity = true;
|
||||
public static int queueSize = 4096;
|
||||
public static long threshold = 10L;
|
||||
private static boolean asyncTargetFindingInitialized;
|
||||
|
||||
@Override
|
||||
@@ -36,21 +35,17 @@ public class AsyncTargetFinding extends ConfigModules {
|
||||
enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
|
||||
// Disable if parallel world ticking is enabled, as they are incompatible.
|
||||
if (enabled && SparklyPaperParallelWorldTicking.enabled) {
|
||||
LeafConfig.LOGGER.warn("Async Target Finding is incompatible with Parallel World Ticking. Disabling Async Target Finding automatically.");
|
||||
LeafConfig.LOGGER.warn("Async target finding is incompatible with Parallel World Ticking. Disabling Async target finding automatically.");
|
||||
enabled = false;
|
||||
}
|
||||
alertOther = config.getBoolean(getBasePath() + ".async-alert-other", true);
|
||||
searchBlock = config.getBoolean(getBasePath() + ".async-search-block", true);
|
||||
searchEntity = config.getBoolean(getBasePath() + ".async-search-entity", true);
|
||||
queueSize = config.getInt(getBasePath() + ".queue-size", 0);
|
||||
threshold = config.getLong(getBasePath() + ".threshold", 0);
|
||||
|
||||
if (queueSize <= 0) {
|
||||
queueSize = 4096;
|
||||
}
|
||||
if (threshold == 0L) {
|
||||
threshold = 10L;
|
||||
}
|
||||
if (!enabled) {
|
||||
alertOther = false;
|
||||
searchEntity = false;
|
||||
|
||||
@@ -15,6 +15,7 @@ public class FastBiomeManagerSeedObfuscation extends ConfigModules {
|
||||
@Experimental
|
||||
public static boolean enabled = false;
|
||||
public static long seedObfuscationKey = ThreadLocalRandom.current().nextLong();
|
||||
public static String seedObfKeyPath;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
@@ -26,7 +27,7 @@ public class FastBiomeManagerSeedObfuscation extends ConfigModules {
|
||||
"""
|
||||
**实验性功能**
|
||||
将原版 BiomeManager 的 SHA-256 种子混淆换成 XXHash."""));
|
||||
seedObfuscationKey = config.getLong(getBasePath() + ".seed-obfuscation-key", seedObfuscationKey,
|
||||
seedObfuscationKey = config.getLong(seedObfKeyPath = getBasePath() + ".seed-obfuscation-key", seedObfuscationKey,
|
||||
config.pickStringRegionBased(
|
||||
"Seed obfuscation key for XXHash.",
|
||||
"XXHash 的混淆种子."));
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.dreeam.leaf.config.modules.opt;
|
||||
|
||||
import org.dreeam.leaf.config.ConfigModules;
|
||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
import org.dreeam.leaf.config.annotations.Experimental;
|
||||
|
||||
public class OptimizeRandomTick extends ConfigModules {
|
||||
|
||||
public String getBasePath() {
|
||||
return EnumConfigCategory.PERF.getBaseKeyName() + ".optimise-random-tick";
|
||||
}
|
||||
|
||||
@Experimental
|
||||
public static boolean enabled = false;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
enabled = config.getBoolean(getBasePath(), enabled);
|
||||
}
|
||||
}
|
||||
@@ -56,11 +56,7 @@ public class FasterRandomSource implements BitRandomSource {
|
||||
|
||||
@Override
|
||||
public final int next(int bits) {
|
||||
if (useDirectImpl) {
|
||||
return (int) ((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
|
||||
}
|
||||
|
||||
return (int) ((seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
|
||||
return (int) ((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
|
||||
}
|
||||
|
||||
public static class FasterRandomSourcePositionalRandomFactory implements PositionalRandomFactory {
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
package org.dreeam.leaf.world;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
|
||||
import java.util.OptionalLong;
|
||||
|
||||
public final class RandomTickSystem {
|
||||
private static final long SCALE = 0x100000L;
|
||||
private static final long CHUNK_BLOCKS = 4096L;
|
||||
|
||||
/// reduce unnecessary sampling and block counting
|
||||
private static final long TICK_MASK = 0b11L;
|
||||
private static final long TICK_MUL = 4L;
|
||||
private static final int BITS_STEP = 2;
|
||||
private static final int BITS_MAX = 60;
|
||||
|
||||
private final LongArrayList queue = new LongArrayList();
|
||||
private final LongArrayList samples = new LongArrayList();
|
||||
private final LongArrayList weights = new LongArrayList();
|
||||
private long weightsSum = 0L;
|
||||
|
||||
private int bits = 60;
|
||||
private long cacheRandom = 0L;
|
||||
|
||||
public void tick(ServerLevel world) {
|
||||
if (weights.isEmpty() || samples.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var random = world.simpleRandom;
|
||||
final long chosen;
|
||||
if (((weightsSum % SCALE) >= boundedNextLong(random, SCALE))) {
|
||||
chosen = weightsSum / SCALE + 1L;
|
||||
} else {
|
||||
chosen = weightsSum / SCALE;
|
||||
}
|
||||
if (chosen == 0L) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long spoke = weightsSum / chosen;
|
||||
if (spoke == 0L) {
|
||||
return;
|
||||
}
|
||||
|
||||
final long[] weightsRaw = weights.elements();
|
||||
final long[] samplesRaw = samples.elements();
|
||||
|
||||
long accumulated = weightsRaw[0];
|
||||
long current = boundedNextLong(random, spoke);
|
||||
int i = 0;
|
||||
while (current < weightsSum) {
|
||||
while (accumulated < current) {
|
||||
i += 1;
|
||||
accumulated += weightsRaw[i];
|
||||
}
|
||||
queue.add(samplesRaw[i]);
|
||||
current += spoke;
|
||||
}
|
||||
while (queue.size() < chosen) {
|
||||
queue.add(samplesRaw[i]);
|
||||
}
|
||||
|
||||
long[] queueRaw = queue.elements();
|
||||
int j = 0;
|
||||
int k;
|
||||
for (k = queue.size() - 3; j < k; j += 4) {
|
||||
final long packed1 = queueRaw[j];
|
||||
final long packed2 = queueRaw[j + 1];
|
||||
final long packed3 = queueRaw[j + 2];
|
||||
final long packed4 = queueRaw[j + 3];
|
||||
final LevelChunk chunk1 = getChunk(world, packed1);
|
||||
final LevelChunk chunk2 = packed1 != packed2 ? getChunk(world, packed2) : chunk1;
|
||||
final LevelChunk chunk3 = packed2 != packed3 ? getChunk(world, packed3) : chunk2;
|
||||
final LevelChunk chunk4 = packed3 != packed4 ? getChunk(world, packed4) : chunk3;
|
||||
if (chunk1 != null) tickBlock(world, chunk1, random);
|
||||
if (chunk2 != null) tickBlock(world, chunk2, random);
|
||||
if (chunk3 != null) tickBlock(world, chunk3, random);
|
||||
if (chunk4 != null) tickBlock(world, chunk4, random);
|
||||
}
|
||||
for (k = queue.size(); j < k; j++) {
|
||||
final LevelChunk chunk = getChunk(world, queueRaw[j]);
|
||||
if (chunk != null) tickBlock(world, chunk, random);
|
||||
}
|
||||
|
||||
weightsSum = 0L;
|
||||
queue.clear();
|
||||
weights.clear();
|
||||
samples.clear();
|
||||
}
|
||||
|
||||
private static LevelChunk getChunk(ServerLevel world, long packed) {
|
||||
return world.chunkSource.getChunkAtIfLoadedImmediately((int) packed, (int) (packed >> 32));
|
||||
}
|
||||
|
||||
private static void tickBlock(ServerLevel world, LevelChunk chunk, RandomSource random) {
|
||||
int count = chunk.leaf$tickingBlocksCount();
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
OptionalLong optionalPos = chunk.leaf$getTickingPos(random.nextInt(count));
|
||||
if (optionalPos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
BlockPos pos = BlockPos.of(optionalPos.getAsLong());
|
||||
BlockState state = chunk.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
|
||||
state.randomTick(world, pos, random);
|
||||
|
||||
final boolean doubleTickFluids = !ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC224294();
|
||||
if (doubleTickFluids) {
|
||||
final FluidState fluidState = state.getFluidState();
|
||||
if (fluidState.isRandomlyTicking()) {
|
||||
fluidState.randomTick(world, pos, random);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tickChunk(
|
||||
RandomSource random,
|
||||
LevelChunk chunk,
|
||||
long tickSpeed
|
||||
) {
|
||||
if (this.bits == BITS_MAX) {
|
||||
this.bits = 0;
|
||||
this.cacheRandom = random.nextLong();
|
||||
} else {
|
||||
this.bits += BITS_STEP;
|
||||
}
|
||||
if ((this.cacheRandom & (TICK_MASK << bits)) == 0L) {
|
||||
long count = chunk.leaf$tickingBlocksCount();
|
||||
if (count != 0L) {
|
||||
long weight = (TICK_MUL * tickSpeed * count * SCALE) / CHUNK_BLOCKS;
|
||||
samples.add(chunk.getPos().longKey);
|
||||
weights.add(weight);
|
||||
weightsSum += weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rng a random number generator to be used as a
|
||||
* source of pseudorandom {@code long} values
|
||||
* @param bound the upper bound (exclusive); must be greater than zero
|
||||
*
|
||||
* @return a pseudorandomly chosen {@code long} value
|
||||
*
|
||||
* @see java.util.random.RandomGenerator#nextLong(long) nextLong(bound)
|
||||
*/
|
||||
public static long boundedNextLong(RandomSource rng, long bound) {
|
||||
final long m = bound - 1;
|
||||
long r = rng.nextLong();
|
||||
if ((bound & m) == 0L) {
|
||||
r &= m;
|
||||
} else {
|
||||
for (long u = r >>> 1;
|
||||
u + m - (r = u % bound) < 0L;
|
||||
u = rng.nextLong() >>> 1)
|
||||
;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ public class OptimizedPoweredRails {
|
||||
|
||||
private static final int UPDATE_FORCE_PLACE = UPDATE_MOVE_BY_PISTON | UPDATE_KNOWN_SHAPE | UPDATE_CLIENTS;
|
||||
|
||||
private static int RAIL_POWER_LIMIT = 8;
|
||||
|
||||
private static final Object2BooleanOpenHashMap<BlockPos> CHECKED_POS_POOL = new Object2BooleanOpenHashMap<>();
|
||||
|
||||
private static void giveShapeUpdate(Level level, BlockState state, BlockPos pos, BlockPos fromPos, Direction direction) {
|
||||
@@ -36,14 +34,6 @@ public class OptimizedPoweredRails {
|
||||
);
|
||||
}
|
||||
|
||||
public static int getRailPowerLimit() {
|
||||
return RAIL_POWER_LIMIT;
|
||||
}
|
||||
|
||||
public static void setRailPowerLimit(int powerLimit) {
|
||||
RAIL_POWER_LIMIT = powerLimit;
|
||||
}
|
||||
|
||||
public static void updateState(PoweredRailBlock self, BlockState state, Level level, BlockPos pos) {
|
||||
boolean shouldBePowered = level.hasNeighborSignal(pos) ||
|
||||
findPoweredRailSignalFaster(self, level, pos, state, true, 0, CHECKED_POS_POOL) ||
|
||||
@@ -97,7 +87,7 @@ public class OptimizedPoweredRails {
|
||||
private static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level level,
|
||||
BlockPos pos, BlockState state, boolean searchForward, int distance,
|
||||
Object2BooleanOpenHashMap<BlockPos> checkedPos) {
|
||||
if (distance >= RAIL_POWER_LIMIT - 1) return false;
|
||||
if (distance >= level.purpurConfig.railActivationRange) return false;
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
@@ -203,7 +193,8 @@ public class OptimizedPoweredRails {
|
||||
|
||||
private static void setRailPositionsPower(PoweredRailBlock self, Level level, BlockPos pos,
|
||||
Object2BooleanOpenHashMap<BlockPos> checkedPos, int[] count, int i, Direction dir) {
|
||||
for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
||||
final int railPowerLimit = level.purpurConfig.railActivationRange;
|
||||
for (int z = 1; z < railPowerLimit; z++) {
|
||||
BlockPos newPos = pos.relative(dir, z);
|
||||
BlockState state = level.getBlockState(newPos);
|
||||
if (checkedPos.containsKey(newPos)) {
|
||||
@@ -229,7 +220,8 @@ public class OptimizedPoweredRails {
|
||||
int[] count, int i, Direction dir) {
|
||||
Object2BooleanOpenHashMap<BlockPos> checkedPos = CHECKED_POS_POOL;
|
||||
checkedPos.clear();
|
||||
for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
||||
final int railPowerLimit = level.purpurConfig.railActivationRange;
|
||||
for (int z = 1; z < railPowerLimit; z++) {
|
||||
BlockPos newPos = pos.relative(dir, z);
|
||||
BlockState state = level.getBlockState(newPos);
|
||||
if (!state.is(self) || !state.getValue(POWERED) || level.hasNeighborSignal(newPos) ||
|
||||
|
||||
BIN
public/image/RainYun.jpg
Normal file
BIN
public/image/RainYun.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -123,7 +123,7 @@ Leaf 根据其上游项目及其他材料,采用多种开源许可证授权,
|
||||
</details>
|
||||
|
||||
## 🔥 特别感谢
|
||||
<a href="https://cloud.swordsman.com.cn/"><img src="../image/JiankeServer.jpg" alt="Jianke Cloud Host" align="left" hspace="8"></a>
|
||||
[](https://cloud.swordsman.com.cn/?i8ab42c) \
|
||||
剑客云 | cloud of swordsman
|
||||
|
||||
如果你想找一个低价高性能、低延迟的云服务商,剑客云是个不错的选择!你可以在 [这里](https://cloud.swordsman.com.cn/?i8ab42c) 注册。
|
||||
@@ -131,7 +131,15 @@ Leaf 根据其上游项目及其他材料,采用多种开源许可证授权,
|
||||
If you want to find a cheaper, high performance, stable, lower latency host, then cloud of swordsman is a good choice! Registers and purchases in [here](https://cloud.swordsman.com.cn/?i8ab42c).
|
||||
|
||||
---
|
||||

|
||||
[](https://www.rainyun.com/NzE2NTc1_) \
|
||||
雨云 | RainYun
|
||||
|
||||
国际多线路选择,配套云存储 — 购买服务后七天内不满意可以申请退订,强大的技术支持团队和高在线率客服。雨云云服务器,用稳定和性价比,助力您快速上云。点击前往 [雨云](https://www.rainyun.com/NzE2NTc1_)。
|
||||
|
||||
Global multi-line routing with cloud storage. Refund available within 7 days. Reliable uptime and expert support. RainYun — stable, cost-effective, and ready for fast cloud deployment. Visit [RainYun]([雨云](https://www.rainyun.com/NzE2NTc1_))
|
||||
|
||||
---
|
||||
 \
|
||||
|
||||
YourKit 通过创新和智能的工具支持开源项目,用于监控和分析 Java 和 .NET 应用程序。
|
||||
YourKit 是 [YourKit Java Profiler](https://www.yourkit.com/java/profiler/)、
|
||||
|
||||
@@ -53,7 +53,7 @@ logsuffix=""
|
||||
# Paper updates
|
||||
if [ -n "$paperHash" ]; then
|
||||
newHash=$(git diff gradle.properties | awk '/^+paperCommit =/{print $NF}')
|
||||
paper=$(getCommits "PaperMC/Paper" "$paperHash" $(echo $newHash | grep . -q && echo $newHash || echo "HEAD"))
|
||||
paper=$(getCommits "PaperMC/Paper" "$paperHash" $(echo $newHash | grep . -q && echo $newHash || echo "main")) # Update this on every version update
|
||||
|
||||
# Updates found
|
||||
if [ -n "$paper" ]; then
|
||||
@@ -64,7 +64,7 @@ fi
|
||||
|
||||
# Purpur updates
|
||||
if [ -n "$purpurHash" ]; then
|
||||
purpur=$(getCommits "PurpurMC/Purpur" "$purpurHash" "HEAD")
|
||||
purpur=$(getCommits "PurpurMC/Purpur" "$purpurHash" "ver/1.21.6") # Update this on every version update
|
||||
|
||||
# Updates found
|
||||
if [ -n "$purpur" ]; then
|
||||
|
||||
Reference in New Issue
Block a user