9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-20 07:29:24 +00:00

Update changes from ver/1.21.4 branch

This commit is contained in:
Dreeam
2025-06-22 10:59:09 +08:00
22 changed files with 905 additions and 524 deletions

View File

@@ -123,7 +123,7 @@ If these excellent projects hadn't existed, Leaf wouldn't have become great.
</details> </details>
## 🔥 Special Thanks ## 🔥 Special Thanks
<a href="https://cloud.swordsman.com.cn/"><img src="public/image/JiankeServer.jpg" alt="Jianke Cloud Host" align="left" hspace="8"></a> [![Jianke Cloud Host](public/image/JiankeServer.jpg)](https://cloud.swordsman.com.cn/?i8ab42c) \
cloud of swordsman | 剑客云 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). 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://cloud.swordsman.com.cn/?i8ab42c) 注册。
--- ---
![YourKit](https://www.yourkit.com/images/yklogo.png) [![雨云](public/image/RainYun.jpg)](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](https://www.yourkit.com/images/yklogo.png) \
YourKit supports open source projects with innovative and intelligent tools YourKit supports open source projects with innovative and intelligent tools
for monitoring and profiling Java and .NET applications. for monitoring and profiling Java and .NET applications.

View File

@@ -3,76 +3,91 @@ From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
Date: Sat, 3 Feb 2024 18:45:53 -0500 Date: Sat, 3 Feb 2024 18:45:53 -0500
Subject: [PATCH] Configurable LibraryLoader maven repos 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. 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` 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 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 --- 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 +++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java
@@ -105,7 +105,7 @@ public class MavenLibraryResolver implements ClassPathLibrary { @@ -3,9 +3,11 @@ package io.papermc.paper.plugin.loader.library.impl;
* dependencies from 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) { public void addRepository(final RemoteRepository remoteRepository) {
- this.repositories.add(remoteRepository); + // Leaf start - Configurable LibraryLoader maven repos
+ this.repositories.add(org.dreeam.leaf.plugin.loader.MavenCentralMirror.getCentralRepo(remoteRepository)); // Leaf - 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 {
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java store.addLibrary(file.toPath());
index cfe41c0a67c8d729b6bd23b0cfa32db3c9db9f74..9f167a9cb4a93a79b8ed709b61214ce0138a875d 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();
- 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 + // Leaf start - Configurable LibraryLoader maven repos
+ this.repositories = repository.newResolutionRepositories( + @org.jspecify.annotations.Nullable
+ session, + private static RemoteRepository getCentralMirrorRepo() {
+ List.of(org.dreeam.leaf.plugin.loader.MavenCentralMirror.getCentralRepo("https://repo.maven.apache.org/maven2")) + String mirrorAddr = System.getProperty("Leaf.library-download-repo");
+ ); + if (mirrorAddr != null) {
+ /* // Dreeam TODO + new RemoteRepository.Builder("central", "default", mirrorAddr).build();
+ this.repositories = repository.newResolutionRepositories(session, List.of( + }
+ new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2").build(), + return null;
+ 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 + // 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..05d3b793bf9cb320774f9f488a3b78bedab6a9d4 100644
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
@@ -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
@Nullable + 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
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 LibraryLoader(@NotNull Logger logger) {
+ this.logger = logger;
+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();
+ }
+}

View File

@@ -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

View File

@@ -1,23 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Leymooo <Vjatseslav.Maspanov@gmail.com> From: AJ Ferguson <fergusonjva@gmail.com>
Date: Wed, 11 Jun 2025 05:30:39 +0300 Date: Mon, 6 Jan 2025 20:31:00 +1100
Subject: [PATCH] PaperPR: Fix excess slot updates / inventory state id desync Subject: [PATCH] Paper: Fix excess slot updates
Removed since Leaf 1.21.6, added in Paper
Original license: GPLv3 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 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) https://github.com/PaperMC/Paper/commit/e714de636543d61fcd3682705484c8a15f4f3ca6
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
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java 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 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -559,7 +559,7 @@ public abstract class AbstractContainerMenu { @@ -559,7 +559,7 @@ public abstract class AbstractContainerMenu {
@@ -25,7 +20,7 @@ index 9dd3187fd968ab95e9d55b4c8cc74e782cc0f241..c5ede24d00f444d04c835af3a7f01542
slot.setChanged(); slot.setChanged();
// CraftBukkit start - Make sure the client has the right slot contents // 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() != 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())); 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 // 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) { if (this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.WORKBENCH || this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.CRAFTING) {

View File

@@ -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()
);

View File

@@ -7,19 +7,16 @@ Original license: MIT
Original project: https://github.com/thebrightspark/AsyncLocator Original project: https://github.com/thebrightspark/AsyncLocator
diff --git a/net/minecraft/server/commands/LocateCommand.java b/net/minecraft/server/commands/LocateCommand.java 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 --- a/net/minecraft/server/commands/LocateCommand.java
+++ b/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()); BlockPos blockPos = BlockPos.containing(source.getPosition());
ServerLevel level = source.getLevel(); ServerLevel level = source.getLevel();
Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER); Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
+ // Leaf start - Asynchronous locator + // Leaf start - Asynchronous locator
+ if (org.dreeam.leaf.config.modules.async.AsyncLocator.enabled) { + 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) + org.dreeam.leaf.async.locate.AsyncLocator.locate(source.getLevel(), holderSet, originPos, 100, false)
+ .thenOnServerThread(pair -> { + .thenOnServerThread(pair -> {
+ stopwatch.stop(); + stopwatch.stop();
@@ -44,11 +41,44 @@ index a734b2597c3491db35d9660e169f8e8b6320900b..8a79a339757d6ac49713bf6db0fb675d
+ +
+ return 0; + return 0;
+ } + }
+ }
+ // Leaf end - Asynchronous locator + // Leaf end - Asynchronous locator
Pair<BlockPos, Holder<Structure>> pair = level.getChunkSource().getGenerator().findNearestMapStructure(level, holderSet, blockPos, 100, false); Pair<BlockPos, Holder<Structure>> pair = level.getChunkSource().getGenerator().findNearestMapStructure(level, holderSet, blockPos, 100, false);
stopwatch.stop(); stopwatch.stop();
if (pair == null) { 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 diff --git a/net/minecraft/world/entity/animal/Dolphin.java b/net/minecraft/world/entity/animal/Dolphin.java
index 23696a5e2871ea07f34d4b4f6a20e2896ac3f5bd..c4fda92e078c9ba745b2548ecaaffffff97fb0fd 100644 index 23696a5e2871ea07f34d4b4f6a20e2896ac3f5bd..c4fda92e078c9ba745b2548ecaaffffff97fb0fd 100644
--- a/net/minecraft/world/entity/animal/Dolphin.java --- a/net/minecraft/world/entity/animal/Dolphin.java

View File

@@ -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);

View File

@@ -100,7 +100,7 @@ index 4535858701b2bb232b9d2feb2af6551526232ddc..e65c62dbe4c1560ae153e4c4344e9194
- // Paper end - detailed watchdog information - // Paper end - detailed watchdog information
} }
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java 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 --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/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 @@ -623,8 +623,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -117,10 +117,10 @@ index 12cf6dc9bac109a4feeeeede5f3762b20ea582bb..b450ac5e19d42765c739311de1566b7b
for (LevelChunk levelChunk : list) { for (LevelChunk levelChunk : list) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java 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 --- a/net/minecraft/server/level/ServerLevel.java
+++ b/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 // Paper end - log detailed entity tick information
public void tickNonPassenger(Entity entity) { public void tickNonPassenger(Entity entity) {
@@ -134,7 +134,7 @@ index 117a8ef98c369bf0919e44fe823d6af0758816b5..47357e1d54563e30b4281c410a1ab70c
entity.setOldPosAndRot(); entity.setOldPosAndRot();
entity.tickCount++; entity.tickCount++;
entity.totalEntityAge++; // Paper - age-like counter for all entities 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()) { for (Entity entity1 : entity.getPassengers()) {
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2 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 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 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 --- a/net/minecraft/world/entity/Entity.java
+++ b/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 @@ -1166,16 +1166,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -1,6 +1,5 @@
package org.dreeam.leaf.async.ai; package org.dreeam.leaf.async.ai;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob; 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 org.dreeam.leaf.util.queue.SpscIntQueue;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.concurrent.locks.LockSupport;
public class AsyncGoalExecutor { public class AsyncGoalExecutor {
protected static final Logger LOGGER = LogManager.getLogger("Leaf Async Goal"); protected static final Logger LOGGER = LogManager.getLogger("Leaf Async Goal");
protected final SpscIntQueue queue; protected final SpscIntQueue queue;
protected final SpscIntQueue wake;
protected final IntArrayList submit;
private final ServerLevel world; private final ServerLevel world;
private long midTickCount = 0L;
public AsyncGoalExecutor(AsyncGoalThread thread, ServerLevel world) { public AsyncGoalExecutor(ServerLevel world) {
this.world = world; this.world = world;
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize); this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
this.wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
this.submit = new IntArrayList();
} }
boolean wake(int id) { boolean wakeAll() {
Entity entity = this.world.getEntities().get(id); boolean success = false;
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();
while (true) { while (true) {
OptionalInt result = this.wake.recv(); OptionalInt result = queue.recv();
if (result.isEmpty()) { if (result.isEmpty()) {
break; break;
} }
int id = result.getAsInt(); int id = result.getAsInt();
if (poll(id) && !this.queue.send(id)) { success = true;
do {
wake(id); wake(id);
} while (poll(id));
}
} }
return success;
} }
private void batchSubmit() { public void tickMob(Mob mob) {
if (submit.isEmpty()) { if (!poll(mob)) {
return; return;
} }
int[] raw = submit.elements(); int entityId = mob.getId();
int size = submit.size(); if (!this.queue.send(entityId)) {
for (int i = 0; i < size; i++) {
int id = raw[i];
if (poll(id) && !this.queue.send(id)) {
do { do {
wake(id); wake(entityId);
} while (poll(id)); } while (poll(mob));
} }
} }
this.submit.clear();
}
public final void midTick() { private void wake(int id) {
if (AsyncTargetFinding.threshold <= 0L || (midTickCount % AsyncTargetFinding.threshold) == 0L) {
batchSubmit();
}
midTickCount += 1;
}
private boolean poll(int id) {
Entity entity = this.world.getEntities().get(id); Entity entity = this.world.getEntities().get(id);
if (entity == null || entity.isRemoved() || !(entity instanceof Mob mob)) { 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 { try {
mob.tickingTarget = true; mob.tickingTarget = true;
boolean a = mob.targetSelector.poll(); boolean a = mob.targetSelector.poll();
@@ -97,8 +65,7 @@ public class AsyncGoalExecutor {
return a || b; return a || b;
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Exception while polling", e); LOGGER.error("Exception while polling", e);
// retry return false;
return true;
} }
} }
} }

View File

@@ -22,26 +22,11 @@ public class AsyncGoalThread extends Thread {
while (RUNNING) { while (RUNNING) {
boolean retry = false; boolean retry = false;
for (ServerLevel level : server.getAllLevels()) { for (ServerLevel level : server.getAllLevels()) {
var exec = level.asyncGoalExecutor; retry |= level.asyncGoalExecutor.wakeAll();
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();
} }
if (!retry) { if (!retry) {
LockSupport.parkNanos(10_000L); LockSupport.parkNanos(1_000_000L);
} }
} }
} }

View File

@@ -7,6 +7,7 @@ import net.minecraft.Util;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dreeam.leaf.config.modules.misc.SentryDSN; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -243,6 +244,7 @@ public class LeafConfig {
List<String> extraHidden = existing != null ? new ArrayList<>(Arrays.asList(existing.split(","))) : new ArrayList<>(); List<String> extraHidden = existing != null ? new ArrayList<>(Arrays.asList(existing.split(","))) : new ArrayList<>();
extraHidden.add(SentryDSN.sentryDsnConfigPath); // Hide Sentry DSN key extraHidden.add(SentryDSN.sentryDsnConfigPath); // Hide Sentry DSN key
extraHidden.add(FastBiomeManagerSeedObfuscation.seedObfKeyPath); // Hide FastBiomeManagerSeedObfuscation key
return extraHidden; return extraHidden;
} }

View File

@@ -16,7 +16,6 @@ public class AsyncTargetFinding extends ConfigModules {
public static boolean searchBlock = true; public static boolean searchBlock = true;
public static boolean searchEntity = true; public static boolean searchEntity = true;
public static int queueSize = 4096; public static int queueSize = 4096;
public static long threshold = 10L;
private static boolean asyncTargetFindingInitialized; private static boolean asyncTargetFindingInitialized;
@Override @Override
@@ -36,21 +35,17 @@ public class AsyncTargetFinding extends ConfigModules {
enabled = config.getBoolean(getBasePath() + ".enabled", enabled); enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
// Disable if parallel world ticking is enabled, as they are incompatible. // Disable if parallel world ticking is enabled, as they are incompatible.
if (enabled && SparklyPaperParallelWorldTicking.enabled) { 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; enabled = false;
} }
alertOther = config.getBoolean(getBasePath() + ".async-alert-other", true); alertOther = config.getBoolean(getBasePath() + ".async-alert-other", true);
searchBlock = config.getBoolean(getBasePath() + ".async-search-block", true); searchBlock = config.getBoolean(getBasePath() + ".async-search-block", true);
searchEntity = config.getBoolean(getBasePath() + ".async-search-entity", true); searchEntity = config.getBoolean(getBasePath() + ".async-search-entity", true);
queueSize = config.getInt(getBasePath() + ".queue-size", 0); queueSize = config.getInt(getBasePath() + ".queue-size", 0);
threshold = config.getLong(getBasePath() + ".threshold", 0);
if (queueSize <= 0) { if (queueSize <= 0) {
queueSize = 4096; queueSize = 4096;
} }
if (threshold == 0L) {
threshold = 10L;
}
if (!enabled) { if (!enabled) {
alertOther = false; alertOther = false;
searchEntity = false; searchEntity = false;

View File

@@ -15,6 +15,7 @@ public class FastBiomeManagerSeedObfuscation extends ConfigModules {
@Experimental @Experimental
public static boolean enabled = false; public static boolean enabled = false;
public static long seedObfuscationKey = ThreadLocalRandom.current().nextLong(); public static long seedObfuscationKey = ThreadLocalRandom.current().nextLong();
public static String seedObfKeyPath;
@Override @Override
public void onLoaded() { public void onLoaded() {
@@ -26,7 +27,7 @@ public class FastBiomeManagerSeedObfuscation extends ConfigModules {
""" """
**实验性功能** **实验性功能**
将原版 BiomeManager 的 SHA-256 种子混淆换成 XXHash.""")); 将原版 BiomeManager 的 SHA-256 种子混淆换成 XXHash."""));
seedObfuscationKey = config.getLong(getBasePath() + ".seed-obfuscation-key", seedObfuscationKey, seedObfuscationKey = config.getLong(seedObfKeyPath = getBasePath() + ".seed-obfuscation-key", seedObfuscationKey,
config.pickStringRegionBased( config.pickStringRegionBased(
"Seed obfuscation key for XXHash.", "Seed obfuscation key for XXHash.",
"XXHash 的混淆种子.")); "XXHash 的混淆种子."));

View File

@@ -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);
}
}

View File

@@ -56,13 +56,9 @@ public class FasterRandomSource implements BitRandomSource {
@Override @Override
public final int next(int bits) { public final int next(int bits) {
if (useDirectImpl) {
return (int) ((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits)); return (int) ((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
} }
return (int) ((seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
}
public static class FasterRandomSourcePositionalRandomFactory implements PositionalRandomFactory { public static class FasterRandomSourcePositionalRandomFactory implements PositionalRandomFactory {
private final long seed; private final long seed;

View File

@@ -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;
}
}

View File

@@ -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 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 final Object2BooleanOpenHashMap<BlockPos> CHECKED_POS_POOL = new Object2BooleanOpenHashMap<>();
private static void giveShapeUpdate(Level level, BlockState state, BlockPos pos, BlockPos fromPos, Direction direction) { 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) { public static void updateState(PoweredRailBlock self, BlockState state, Level level, BlockPos pos) {
boolean shouldBePowered = level.hasNeighborSignal(pos) || boolean shouldBePowered = level.hasNeighborSignal(pos) ||
findPoweredRailSignalFaster(self, level, pos, state, true, 0, CHECKED_POS_POOL) || 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, private static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level level,
BlockPos pos, BlockState state, boolean searchForward, int distance, BlockPos pos, BlockState state, boolean searchForward, int distance,
Object2BooleanOpenHashMap<BlockPos> checkedPos) { Object2BooleanOpenHashMap<BlockPos> checkedPos) {
if (distance >= RAIL_POWER_LIMIT - 1) return false; if (distance >= level.purpurConfig.railActivationRange) return false;
int x = pos.getX(); int x = pos.getX();
int y = pos.getY(); int y = pos.getY();
int z = pos.getZ(); int z = pos.getZ();
@@ -203,7 +193,8 @@ public class OptimizedPoweredRails {
private static void setRailPositionsPower(PoweredRailBlock self, Level level, BlockPos pos, private static void setRailPositionsPower(PoweredRailBlock self, Level level, BlockPos pos,
Object2BooleanOpenHashMap<BlockPos> checkedPos, int[] count, int i, Direction dir) { 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); BlockPos newPos = pos.relative(dir, z);
BlockState state = level.getBlockState(newPos); BlockState state = level.getBlockState(newPos);
if (checkedPos.containsKey(newPos)) { if (checkedPos.containsKey(newPos)) {
@@ -229,7 +220,8 @@ public class OptimizedPoweredRails {
int[] count, int i, Direction dir) { int[] count, int i, Direction dir) {
Object2BooleanOpenHashMap<BlockPos> checkedPos = CHECKED_POS_POOL; Object2BooleanOpenHashMap<BlockPos> checkedPos = CHECKED_POS_POOL;
checkedPos.clear(); 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); BlockPos newPos = pos.relative(dir, z);
BlockState state = level.getBlockState(newPos); BlockState state = level.getBlockState(newPos);
if (!state.is(self) || !state.getValue(POWERED) || level.hasNeighborSignal(newPos) || if (!state.is(self) || !state.getValue(POWERED) || level.hasNeighborSignal(newPos) ||

BIN
public/image/RainYun.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -123,7 +123,7 @@ Leaf 根据其上游项目及其他材料,采用多种开源许可证授权,
</details> </details>
## 🔥 特别感谢 ## 🔥 特别感谢
<a href="https://cloud.swordsman.com.cn/"><img src="../image/JiankeServer.jpg" alt="Jianke Cloud Host" align="left" hspace="8"></a> [![Jianke Cloud Host](../image/JiankeServer.jpg)](https://cloud.swordsman.com.cn/?i8ab42c) \
剑客云 | cloud of swordsman 剑客云 | cloud of swordsman
如果你想找一个低价高性能、低延迟的云服务商,剑客云是个不错的选择!你可以在 [这里](https://cloud.swordsman.com.cn/?i8ab42c) 注册。 如果你想找一个低价高性能、低延迟的云服务商,剑客云是个不错的选择!你可以在 [这里](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). 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).
--- ---
![YourKit](https://www.yourkit.com/images/yklogo.png) [![雨云](../image/RainYun.jpg)](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](https://www.yourkit.com/images/yklogo.png) \
YourKit 通过创新和智能的工具支持开源项目,用于监控和分析 Java 和 .NET 应用程序。 YourKit 通过创新和智能的工具支持开源项目,用于监控和分析 Java 和 .NET 应用程序。
YourKit 是 [YourKit Java Profiler](https://www.yourkit.com/java/profiler/)、 YourKit 是 [YourKit Java Profiler](https://www.yourkit.com/java/profiler/)、

View File

@@ -53,7 +53,7 @@ logsuffix=""
# Paper updates # Paper updates
if [ -n "$paperHash" ]; then if [ -n "$paperHash" ]; then
newHash=$(git diff gradle.properties | awk '/^+paperCommit =/{print $NF}') 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 # Updates found
if [ -n "$paper" ]; then if [ -n "$paper" ]; then
@@ -64,7 +64,7 @@ fi
# Purpur updates # Purpur updates
if [ -n "$purpurHash" ]; then 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 # Updates found
if [ -n "$purpur" ]; then if [ -n "$purpur" ]; then