Compare commits
52 Commits
1.20.2-716
...
ver/1.20.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
365639d7db | ||
|
|
5257a5ccc9 | ||
|
|
a1fffec02a | ||
|
|
79a21ab81a | ||
|
|
d577729ca2 | ||
|
|
b41225df65 | ||
|
|
3a473302d0 | ||
|
|
a1df619285 | ||
|
|
a4ba907b33 | ||
|
|
aa5acdd1b5 | ||
|
|
f9b62e717e | ||
|
|
7d04bb5038 | ||
|
|
0e70acaa9c | ||
|
|
0872f03352 | ||
|
|
f5550b8cc1 | ||
|
|
909b208b67 | ||
|
|
b159640ebe | ||
|
|
76aa79aa3c | ||
|
|
f2d8696e94 | ||
|
|
31e86623e1 | ||
|
|
a290a8d6a0 | ||
|
|
31a559f1d9 | ||
|
|
be9ff6c4ce | ||
|
|
51ad682270 | ||
|
|
b396452d5f | ||
|
|
7d5174c23d | ||
|
|
09d5da9bbb | ||
|
|
a3ed860ba1 | ||
|
|
cee866c80f | ||
|
|
ad71c13e4b | ||
|
|
a03519f434 | ||
|
|
6470c6124d | ||
|
|
df20d94756 | ||
|
|
65378b9e26 | ||
|
|
c252b863d5 | ||
|
|
54fd31cb6c | ||
|
|
7465ab1daf | ||
|
|
4f43e7845c | ||
|
|
5e62e78720 | ||
|
|
1d4276694e | ||
|
|
3bca6a9846 | ||
|
|
ff831edffa | ||
|
|
b2689cc08c | ||
|
|
ae5a4e8e67 | ||
|
|
d2655c4228 | ||
|
|
d58d0d3db5 | ||
|
|
09e71b6759 | ||
|
|
9080749e08 | ||
|
|
66166c485c | ||
|
|
d8d3e9b85b | ||
|
|
acd8e7916c | ||
|
|
140ccf5e74 |
@@ -51,13 +51,13 @@ jobs:
|
||||
export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
|
||||
./gradlew publish
|
||||
- name: Rename jar file
|
||||
run: mv build/libs/Luminol-paperclip-1.20.2-R0.1-SNAPSHOT-reobf.jar build/libs/lunminol-1.20.2-paperclip.jar
|
||||
run: mv build/libs/Luminol-paperclip-1.20.2-R0.1-SNAPSHOT-reobf.jar build/libs/luminol-1.20.2-paperclip.jar
|
||||
- name: Release Artifacts
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
release_name: "Luminol MC1.20.2 - ${{ github.event.repository.updated_at}}"
|
||||
tag: "1.20.2-${{ github.run_id }}"
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
file: "build/libs/lunminol-1.20.2-paperclip.jar"
|
||||
file: "build/libs/luminol-1.20.2-paperclip.jar"
|
||||
file_glob: true
|
||||
prerelease: false
|
||||
prerelease: true
|
||||
4
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Era4FunMC
|
||||
Copyright (c) 2024 LuminolMC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
12
README.md
@@ -1,12 +1,17 @@
|
||||
<img src="./public/image/Luminol_5.png" alt="Logo" align="right" width="250">
|
||||
|
||||
# Luminol
|
||||
|
||||
<h4>Luminol is a folia fork with many useful optimizations, configurable vanilla features, and more API supports, and it was designed for survival and anarchy servers</h4>
|
||||
|
||||
**English** | [中文](./README_CN.md)
|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/LuminolMC/Luminol/issues)
|
||||

|
||||

|
||||

|
||||
|
||||
<h4>Luminol is a folia fork with many useful optimizations, configurable vanilla features, and more API supports, and it was designed for survival and anarchy servers</h4>
|
||||
|
||||
## Features
|
||||
- Configurable vanilla features
|
||||
- Tpsbar support
|
||||
@@ -37,3 +42,6 @@ For maven
|
||||
<version>1.20.2-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## BStats
|
||||

|
||||
|
||||
48
README_CN.md
Normal file
@@ -0,0 +1,48 @@
|
||||
<img src="./public/image/Luminol_5.png" alt="Logo" align="right" width="250">
|
||||
|
||||
# Luminol
|
||||
|
||||
<h4>Luminol 是一个基于folia的分支,具有许多有用的优化、可配置的原版特性和更多的API支持,它专为生存和无政府服务器设计</h4>
|
||||
|
||||
[English](./README.md) | **中文**
|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/LuminolMC/Luminol/issues)
|
||||

|
||||

|
||||

|
||||
|
||||
## 特性
|
||||
- 可配置的原版特性
|
||||
- Tpsbar 支持
|
||||
- 线性区域文件格式 (from kaiiju)
|
||||
- 对单线程区域性能的优化
|
||||
- 更多的插件开发API支持(进行中)
|
||||
|
||||
## 下载
|
||||
任何版本都可以在 [release](https://github.com/LuminolMC/Luminol/releases), 中找到,您也可以通过以下步骤自己构建。
|
||||
|
||||
## 构建
|
||||
要构建一个paperclip jar,你需要运行以下命令。你可以在build/libs中找到jar(注意:需要JDK17)
|
||||
```shell
|
||||
./gradlew applyPatches && ./gradlew createReobfPaperclipJar
|
||||
```
|
||||
## 使用API
|
||||
使用 Gradle:
|
||||
```kotlin
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:1.20.2-R0.1-SNAPSHOT")
|
||||
}
|
||||
```
|
||||
使用 Maven
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>1.20.2-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## BStats
|
||||

|
||||
|
||||
@@ -93,3 +93,41 @@ paperweight {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "githubPackage"
|
||||
url = uri("https://maven.pkg.github.com/LuminolMC/Luminol")
|
||||
|
||||
credentials.username = System.getenv("GITHUB_USERNAME")
|
||||
credentials.password = System.getenv("GITHUB_TOKEN")
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "moliaMavenRepo"
|
||||
url = uri("https://maven.nostal.ink/repository/maven-snapshots/")
|
||||
|
||||
credentials.username = System.getenv("MAVEN_REPO_USER")
|
||||
credentials.password = System.getenv("MAVEN_REPO_PASSWORD")
|
||||
}
|
||||
|
||||
publications {
|
||||
register<MavenPublication>("gpr") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
if (project.hasProperty("publishDevBundle")) {
|
||||
publications.create<MavenPublication>("devBundle") {
|
||||
artifact(tasks.generateDevelopmentBundle) {
|
||||
artifactId = "dev-bundle"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
506
patches/api/0002-Leaves-fakeplayer-API.patch
Normal file
@@ -0,0 +1,506 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Tue, 30 Jan 2024 09:03:08 +0000
|
||||
Subject: [PATCH] Leaves fakeplayer API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index b7e1c8bd8dd38e1a9e74925740b22dad61a75f49..5ee1ba3847599ac67b5cd8ca26e61b1231c45dcd 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -58,6 +58,7 @@ import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import io.papermc.paper.util.JarManifests; // Paper
|
||||
+import top.leavesmc.leaves.entity.BotManager;
|
||||
|
||||
/**
|
||||
* Represents the Bukkit core, for version and Server singleton handling
|
||||
@@ -2836,6 +2837,17 @@ public final class Bukkit {
|
||||
}
|
||||
// Folia end - region threading API
|
||||
|
||||
+ // Leaves start - Bot API
|
||||
+ /**
|
||||
+ * Returns a bot manager.
|
||||
+ *
|
||||
+ * @return Bot Manager
|
||||
+ */
|
||||
+ public static @NotNull BotManager getBotManager() {
|
||||
+ return server.getBotManager();
|
||||
+ }
|
||||
+ // Leaves end - Bot API
|
||||
+
|
||||
@NotNull
|
||||
public static Server.Spigot spigot() {
|
||||
return server.spigot();
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 85b169c04f44431363d4e14d4857140f160ceace..9e12552aca127892d122a2616d303d3cdfc67416 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -58,6 +58,7 @@ import org.bukkit.util.CachedServerIcon;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
+import top.leavesmc.leaves.entity.BotManager;
|
||||
|
||||
/**
|
||||
* Represents a server implementation.
|
||||
@@ -2479,4 +2480,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
public boolean isGlobalTickThread();
|
||||
// Folia end - region threading API
|
||||
+
|
||||
+
|
||||
+ // Leaves start - Bot API
|
||||
+ /**
|
||||
+ * Returns a bot manager.
|
||||
+ *
|
||||
+ * @return Bot Manager
|
||||
+ */
|
||||
+ @NotNull BotManager getBotManager();
|
||||
+ // Leaves end - Bot API
|
||||
}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/entity/Bot.java b/src/main/java/top/leavesmc/leaves/entity/Bot.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8816683c795f9be6a4f112203cfac3f59d8faba5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/entity/Bot.java
|
||||
@@ -0,0 +1,46 @@
|
||||
+package top.leavesmc.leaves.entity;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+import top.leavesmc.leaves.entity.botaction.LeavesBotAction;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a fakeplayer
|
||||
+ */
|
||||
+public interface Bot extends Player {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the fakeplayer skin
|
||||
+ *
|
||||
+ * @return fakeplayer skin name
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getSkinName();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the fakeplayer name without prefix and suffix
|
||||
+ *
|
||||
+ * @return fakeplayer real name
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public String getRealName();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the fakeplayer action with args.
|
||||
+ *
|
||||
+ * @param action action name
|
||||
+ * @param player player who create this action
|
||||
+ * @param args passed action arguments
|
||||
+ */
|
||||
+ public boolean setBotAction(@NotNull String action, @NotNull Player player, @NotNull String[] args);
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the fakeplayer action with args.
|
||||
+ *
|
||||
+ * @param action leaves bot action
|
||||
+ * @param player player who create this action
|
||||
+ * @param args passed action arguments
|
||||
+ */
|
||||
+ public boolean setBotAction(@NotNull LeavesBotAction action, @NotNull Player player, @NotNull String[] args);
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/entity/BotManager.java b/src/main/java/top/leavesmc/leaves/entity/BotManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f2258027b2ed4bfcf7feda2e9075b1a1a05a85b6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/entity/BotManager.java
|
||||
@@ -0,0 +1,107 @@
|
||||
+package top.leavesmc.leaves.entity;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.util.Consumer;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+import top.leavesmc.leaves.entity.botaction.CustomBotAction;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+/**
|
||||
+ * Simple fakeplayer manager
|
||||
+ */
|
||||
+public interface BotManager {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets a fakeplayer object by the given uuid.
|
||||
+ *
|
||||
+ * @param uuid the uuid to look up
|
||||
+ * @return a fakeplayer if one was found, null otherwise
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Bot getBot(@NotNull UUID uuid);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets a fakeplayer object by the given name.
|
||||
+ *
|
||||
+ * @param name the name to look up
|
||||
+ * @return a fakeplayer if one was found, null otherwise
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Bot getBot(@NotNull String name);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a fakeplayer with given param.
|
||||
+ * <p>
|
||||
+ * prefix and suffix will not be added.
|
||||
+ *
|
||||
+ * @param name fakeplayer name
|
||||
+ * @param realName fakeplayer real name
|
||||
+ * @param skin fakeplayer skin arr
|
||||
+ * @param skinName fakeplayer skin name
|
||||
+ * @param location a location will create fakeplayer
|
||||
+ * @return a fakeplayer if success, null otherwise
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public Bot createBot(@NotNull String name, @NotNull String realName, @Nullable String[] skin, @Nullable String skinName, @NotNull Location location);
|
||||
+
|
||||
+ /**
|
||||
+ * Creates a fakeplayer with given param.
|
||||
+ *
|
||||
+ * @param name fakeplayer name
|
||||
+ * @param skinName fakeplayer skin name
|
||||
+ * @param location a location will create fakeplayer
|
||||
+ * @param consumer a consumer after create fakeplayer success
|
||||
+ */
|
||||
+ public void createBot(@NotNull String name, @Nullable String skinName, @NotNull Location location, @Nullable Consumer<Bot> consumer);
|
||||
+
|
||||
+ /**
|
||||
+ * Removes a fakeplayer object by the given name.
|
||||
+ *
|
||||
+ * @param name the name to look up
|
||||
+ */
|
||||
+ public void removeBot(@NotNull String name);
|
||||
+
|
||||
+ /**
|
||||
+ * Removes a fakeplayer object by the given uuid.
|
||||
+ *
|
||||
+ * @param uuid the uuid to look up
|
||||
+ */
|
||||
+ public void removeBot(@NotNull UUID uuid);
|
||||
+
|
||||
+ /**
|
||||
+ * Removes all fakeplayers.
|
||||
+ */
|
||||
+ public void removeAllBots();
|
||||
+
|
||||
+ /**
|
||||
+ * Save fakeplayers data if resident-fakeplayer is true, or remove all fakeplayer.
|
||||
+ */
|
||||
+ public void saveOrRemoveAllBots();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets a view of all currently logged in fakeplayers. This view is a reused object, making some operations like Collection.size() zero-allocation.
|
||||
+ *
|
||||
+ * @return a view of fakeplayers.
|
||||
+ */
|
||||
+ public Collection<Bot> getBots();
|
||||
+
|
||||
+ /**
|
||||
+ * Register a custom bot action.
|
||||
+ *
|
||||
+ * @param name action name
|
||||
+ * @param action action executor
|
||||
+ * @return true if success, or false
|
||||
+ */
|
||||
+ public boolean registerCustomBotAction(String name, CustomBotAction action);
|
||||
+
|
||||
+ /**
|
||||
+ * Unregister a custom bot action.
|
||||
+ *
|
||||
+ * @param name action name
|
||||
+ * @return true if success, or false
|
||||
+ */
|
||||
+ public boolean unregisterCustomBotAction(String name);
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/entity/botaction/CustomBotAction.java b/src/main/java/top/leavesmc/leaves/entity/botaction/CustomBotAction.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7abf4eef22e40468929e724ebc07a97b0b2a05f3
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/entity/botaction/CustomBotAction.java
|
||||
@@ -0,0 +1,52 @@
|
||||
+package top.leavesmc.leaves.entity.botaction;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+import top.leavesmc.leaves.entity.Bot;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a class which contains methods for a custom bot action
|
||||
+ */
|
||||
+public interface CustomBotAction {
|
||||
+
|
||||
+ /**
|
||||
+ * Executes the action, returning its success.
|
||||
+ *
|
||||
+ * @param bot bot of the action
|
||||
+ * @return true if once action finish, otherwise false
|
||||
+ */
|
||||
+ public boolean doTick(Bot bot);
|
||||
+
|
||||
+ /**
|
||||
+ * Created a new action instance.
|
||||
+ *
|
||||
+ * @param player player who create this action
|
||||
+ * @param args passed action arguments
|
||||
+ * @return a new action instance with given args
|
||||
+ */
|
||||
+ public @Nullable CustomBotAction getNew(Player player, String[] args);
|
||||
+
|
||||
+ /**
|
||||
+ * Requests a list of possible completions for a action argument.
|
||||
+ *
|
||||
+ * @return A List of a List of possible completions for the argument.
|
||||
+ */
|
||||
+ public @NotNull List<List<String>> getTabComplete();
|
||||
+
|
||||
+ /**
|
||||
+ * Return a ticks to wait between {@link CustomBotAction#doTick(Bot)}
|
||||
+ *
|
||||
+ * @return the ticks to wait between runs
|
||||
+ */
|
||||
+ public int getTickDelay();
|
||||
+
|
||||
+ /**
|
||||
+ * Return a number of times {@link CustomBotAction#doTick(Bot)} can return true
|
||||
+ *
|
||||
+ * @return the number of times an action can be executed
|
||||
+ */
|
||||
+ public int getNumber();
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/entity/botaction/LeavesBotAction.java b/src/main/java/top/leavesmc/leaves/entity/botaction/LeavesBotAction.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e298722319ff0cfd52e531693ea3767e5f9a3d52
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/entity/botaction/LeavesBotAction.java
|
||||
@@ -0,0 +1,32 @@
|
||||
+package top.leavesmc.leaves.entity.botaction;
|
||||
+
|
||||
+/**
|
||||
+ * A Leaves bot action enum
|
||||
+ */
|
||||
+public enum LeavesBotAction {
|
||||
+ ATTACK("attack"),
|
||||
+ ATTACK_SELF("attack_self"),
|
||||
+ BREAK("break"),
|
||||
+ DROP("drop"),
|
||||
+ FISH("fish"),
|
||||
+ JUMP("jump"),
|
||||
+ LAY("lay"),
|
||||
+ LOOK("look"),
|
||||
+ ROTATE("rotate"),
|
||||
+ SNEAK("sneak"),
|
||||
+ STOP("stop"),
|
||||
+ SWIM("swim"),
|
||||
+ USE("use"),
|
||||
+ USE_ON("use_on"),
|
||||
+ USE_TO("use_to");
|
||||
+
|
||||
+ private final String name;
|
||||
+
|
||||
+ private LeavesBotAction(String name) {
|
||||
+ this.name = name;
|
||||
+ }
|
||||
+
|
||||
+ public String getName() {
|
||||
+ return name;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/event/bot/BotCreateEvent.java b/src/main/java/top/leavesmc/leaves/event/bot/BotCreateEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7cf1eb4eb3d2fe9310f9272ec53208632b87b49b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/event/bot/BotCreateEvent.java
|
||||
@@ -0,0 +1,106 @@
|
||||
+package top.leavesmc.leaves.event.bot;
|
||||
+
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Call when a fakeplayer creates a server
|
||||
+ */
|
||||
+public class BotCreateEvent extends Event implements Cancellable {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ private final String bot;
|
||||
+ private final String skin;
|
||||
+ private String joinMessage;
|
||||
+ private Location createLocation;
|
||||
+ private boolean cancel = false;
|
||||
+
|
||||
+ public BotCreateEvent(@NotNull final String who, @NotNull final String skin, @NotNull final Location createLocation, @Nullable final String joinMessage) {
|
||||
+ this.bot = who;
|
||||
+ this.skin = skin;
|
||||
+ this.joinMessage = joinMessage;
|
||||
+ this.createLocation = createLocation;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the fakeplayer name
|
||||
+ *
|
||||
+ * @return fakeplayer name
|
||||
+ */
|
||||
+ public String getBot() {
|
||||
+ return bot;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the join message to send to all online players
|
||||
+ *
|
||||
+ * @return string join message. Can be null
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getJoinMessage() {
|
||||
+ return joinMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the join message to send to all online players
|
||||
+ *
|
||||
+ * @param joinMessage join message. If null, no message will be sent
|
||||
+ */
|
||||
+ public void setJoinMessage(@Nullable String joinMessage) {
|
||||
+ this.joinMessage = joinMessage;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the location to create the fakeplayer
|
||||
+ *
|
||||
+ * @return Location to create the fakeplayer
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public Location getCreateLocation() {
|
||||
+ return createLocation;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the location to create the fakeplayer
|
||||
+ *
|
||||
+ * @param createLocation location to create the fakeplayer
|
||||
+ */
|
||||
+ public void setCreateLocation(@NotNull Location createLocation) {
|
||||
+ this.createLocation = createLocation;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the fakeplayer skin
|
||||
+ *
|
||||
+ * @return fakeplayer skin name
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public String getSkin() {
|
||||
+ return skin;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancel;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ this.cancel = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/event/bot/BotEvent.java b/src/main/java/top/leavesmc/leaves/event/bot/BotEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4a4fe07ce965d4a97e0d8105a91310dac7d1343c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/event/bot/BotEvent.java
|
||||
@@ -0,0 +1,31 @@
|
||||
+package top.leavesmc.leaves.event.bot;
|
||||
+
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import top.leavesmc.leaves.entity.Bot;
|
||||
+
|
||||
+/**
|
||||
+ * Represents a fakeplayer related event
|
||||
+ */
|
||||
+public abstract class BotEvent extends Event {
|
||||
+ protected Bot bot;
|
||||
+
|
||||
+ public BotEvent(@NotNull final Bot who) {
|
||||
+ bot = who;
|
||||
+ }
|
||||
+
|
||||
+ public BotEvent(@NotNull final Bot who, boolean async) { // Paper - public
|
||||
+ super(async);
|
||||
+ bot = who;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the fakeplayer involved in this event
|
||||
+ *
|
||||
+ * @return Fakeplayer who is involved in this event
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public final Bot getBot() {
|
||||
+ return bot;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/event/bot/BotJoinEvent.java b/src/main/java/top/leavesmc/leaves/event/bot/BotJoinEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..10afa5c7fd4ee8a4e72d64f8ca9bf8731ec2ad61
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/event/bot/BotJoinEvent.java
|
||||
@@ -0,0 +1,27 @@
|
||||
+package top.leavesmc.leaves.event.bot;
|
||||
+
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import top.leavesmc.leaves.entity.Bot;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a fakeplayer joins a server
|
||||
+ */
|
||||
+public class BotJoinEvent extends BotEvent {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ public BotJoinEvent(@NotNull Bot who) {
|
||||
+ super(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
||||
@@ -109,7 +109,7 @@ index 0000000000000000000000000000000000000000..ac8f0e3bf130ba6dfd7202e2f4803522
|
||||
+}
|
||||
diff --git a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3023bc0e7420870e80dda75f7b044069b61a2b7e
|
||||
index 0000000000000000000000000000000000000000..baec715e0c20e920ccb99f2f07d84fcb6f2b434e
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java
|
||||
@@ -0,0 +1,204 @@
|
||||
@@ -236,7 +236,7 @@ index 0000000000000000000000000000000000000000..3023bc0e7420870e80dda75f7b044069
|
||||
+ Placeholder.component("ping",getPingComponent(player.getPing()))
|
||||
+ ));
|
||||
+ bar.color(barColorFromTps(tps));
|
||||
+ bar.progress((float) Math.min(mspt / 50,1.0));
|
||||
+ bar.progress((float) Math.min((float)1,Math.max(mspt / 50,0)));
|
||||
+ }
|
||||
+
|
||||
+ private static @NotNull Component getPingComponent(int ping){
|
||||
|
||||
@@ -25,7 +25,7 @@ index d032786938db9725e1be72dae63a1387bcb69d79..dcc52141b34b87a67c3d6070b68b58af
|
||||
if (tpsbarEnabled){
|
||||
initTpsbar();
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 97bfb92e52c3c5ef1cd22afe2b97c204eb45025a..710e87e388095f28af4983a04cb89ddb6be61986 100644
|
||||
index d7a280427442bac8cc8ccb542d24d4e0901df70a..755294e3f5b3fbcfbdc0cc85627b2487663ce591 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -18,6 +18,9 @@ import java.util.Optional;
|
||||
@@ -38,7 +38,7 @@ index 97bfb92e52c3c5ef1cd22afe2b97c204eb45025a..710e87e388095f28af4983a04cb89ddb
|
||||
import net.minecraft.BlockUtil;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.CrashReport;
|
||||
@@ -835,18 +838,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -836,18 +839,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
Entity entity = this.getCamera();
|
||||
|
||||
@@ -58,7 +58,7 @@ index 97bfb92e52c3c5ef1cd22afe2b97c204eb45025a..710e87e388095f28af4983a04cb89ddb
|
||||
CriteriaTriggers.TICK.trigger(this);
|
||||
if (this.levitationStartPos != null) {
|
||||
CriteriaTriggers.LEVITATION.trigger(this, this.levitationStartPos, this.tickCount - this.levitationStartTime);
|
||||
@@ -855,6 +847,38 @@ public class ServerPlayer extends Player {
|
||||
@@ -856,6 +848,38 @@ public class ServerPlayer extends Player {
|
||||
this.trackStartFallingPosition();
|
||||
this.trackEnteredOrExitedLavaOnVehicle();
|
||||
this.advancements.flushDirty(this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Wed, 29 Nov 2023 21:15:32 +0800
|
||||
Subject: [PATCH] Add config for offline mod warning
|
||||
Subject: [PATCH] Add config for offline mode warning
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -475,7 +475,7 @@ index 0000000000000000000000000000000000000000..130d61324679c8600faa52255f3ad99f
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 7ada58f2fa83a47908723bdf1e5c5fbbc2f5ffa9..e8cd180bab5c196db09ded74aea676b4412fc6e9 100644
|
||||
index 7ada58f2fa83a47908723bdf1e5c5fbbc2f5ffa9..dee892ef5f999b693507e7de909d639ce7875780 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
@@ -503,8 +503,8 @@ index 7ada58f2fa83a47908723bdf1e5c5fbbc2f5ffa9..e8cd180bab5c196db09ded74aea676b4
|
||||
acquirePoiForStuckEntityInterval = get("optimizations.acquire_poi_for_stuck_entity_interval", acquirePoiForStuckEntityInterval);
|
||||
+
|
||||
+ asyncPathProcessing = get("optimizations.async_pathfinding.enabled",asyncPathProcessing,"Config to enable the async pathfinder.");
|
||||
+ asyncPathProcessingMaxThreads = get("optimization.async_pathfinding.max-threads", asyncPathProcessingMaxThreads,"If it was set to 0(default),the thread count will be auto set(a quarter of the CPU thread count)");
|
||||
+ asyncPathProcessingKeepalive = get("optimization.async_pathfinding.keepalive", asyncPathProcessingKeepalive);
|
||||
+ asyncPathProcessingMaxThreads = get("optimizations.async_pathfinding.max-threads", asyncPathProcessingMaxThreads,"If it was set to 0(default),the thread count will be auto set(a quarter of the CPU thread count)");
|
||||
+ asyncPathProcessingKeepalive = get("optimizations.async_pathfinding.keepalive", asyncPathProcessingKeepalive);
|
||||
+ if (asyncPathProcessingMaxThreads < 0)
|
||||
+ asyncPathProcessingMaxThreads = Math.max(Runtime.getRuntime().availableProcessors() + asyncPathProcessingMaxThreads, 1);
|
||||
+ else if (asyncPathProcessingMaxThreads == 0)
|
||||
|
||||
@@ -451,3 +451,33 @@ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..c470eafef884075b6e4d170adc2ced96
|
||||
}
|
||||
|
||||
public void removeTicketsOnClosing() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 5caca2a34849189ea42d2699f6d8672e0d7251cb..b21243d494fd1989e7d6c2b98b08e090dc2f38b7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -1,6 +1,9 @@
|
||||
package net.minecraft.world.level;
|
||||
|
||||
+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
|
||||
import com.mojang.logging.LogUtils;
|
||||
+import io.papermc.paper.threadedregions.RegionizedServer;
|
||||
+import io.papermc.paper.util.TickThread;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
@@ -117,6 +120,15 @@ public final class NaturalSpawner {
|
||||
object2intopenhashmap.addTo(enumcreaturetype, 1);
|
||||
// Paper start
|
||||
if (countMobs) {
|
||||
+ //Luminol start - Async mob spawning
|
||||
+ if (!TickThread.isTickThread()){
|
||||
+ RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(chunk.level,chunk.locX,chunk.locZ,()->{
|
||||
+ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity);
|
||||
+ });
|
||||
+ return;
|
||||
+ }
|
||||
+ //Luminol end
|
||||
+
|
||||
chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity);
|
||||
}
|
||||
// Paper end
|
||||
|
||||
77
patches/server/0043-Purpur-use-alternative-keep-alive.patch
Normal file
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Sun, 17 Dec 2023 20:32:49 +0800
|
||||
Subject: [PATCH] Purpur use alternative keep alive
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 6edafcdbc188cd6c78e4c4237363e41d927a665e..a62680768068b611fe723fedeb617d42c643e59e 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -64,6 +64,7 @@ public class LuminolConfig {
|
||||
public static int asyncPathProcessingMaxThreads = 0;
|
||||
public static int asyncPathProcessingKeepalive = 60;
|
||||
public static boolean enableAsyncMobSpawning = false;
|
||||
+ public static boolean useAlternateKeepAlive = false;
|
||||
|
||||
public static void init() throws IOException {
|
||||
PARENT_FOLDER.mkdir();
|
||||
@@ -192,6 +193,7 @@ public class LuminolConfig {
|
||||
asyncPathProcessingMaxThreads = 0;
|
||||
enableAsyncMobSpawning = get("optimizations.enable_async_mob_spawning",enableAsyncMobSpawning);
|
||||
RegionizedWorldData.initMobSpawningExecutor();
|
||||
+ useAlternateKeepAlive = get("optimizations.enable_alternative_keep_alive_handling",useAlternateKeepAlive,"Enabling this sends a keepalive packet once per second to a player, and only kicks for timeout if none of them were responded to in 30 seconds. Responding to any of them in any order will keep the player connected. AKA, it won't kick your players because one packet gets dropped somewhere along the lines(From purpur)");
|
||||
}
|
||||
|
||||
public static <T> T get(String key,T def){
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 2bb944cef9bc8c5e56023ef20921ef13509d4823..9d23285f97ac5d90eb177ddc325281fa197d7f76 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -51,6 +51,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
private long keepAliveTime = Util.getMillis(); // Paper
|
||||
private boolean keepAlivePending;
|
||||
private long keepAliveChallenge;
|
||||
+ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur
|
||||
private int latency;
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
@@ -91,6 +92,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||
+ // Purpur start
|
||||
+ if (me.earthme.luminol.LuminolConfig.useAlternateKeepAlive) {
|
||||
+ long id = packet.getId();
|
||||
+ if (keepAlives.size() > 0 && keepAlives.contains(id)) {
|
||||
+ int ping = (int) (Util.getMillis() - id);
|
||||
+ this.latency = (this.latency * 3 + ping) / 4;
|
||||
+ keepAlives.clear(); // we got a valid response, lets roll with it and forget the rest
|
||||
+ }
|
||||
+ } else
|
||||
+ // Purpur end
|
||||
//PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - This shouldn't be on the main thread
|
||||
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||
int i = (int) (Util.getMillis() - this.keepAliveTime);
|
||||
@@ -197,6 +208,21 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
long currentTime = Util.getMillis();
|
||||
long elapsedTime = currentTime - this.keepAliveTime;
|
||||
|
||||
+ // Purpur start
|
||||
+ if (me.earthme.luminol.LuminolConfig.useAlternateKeepAlive) {
|
||||
+ if (elapsedTime >= 1000L) { // 1 second
|
||||
+ if (!processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) {
|
||||
+ LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName());
|
||||
+ disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
|
||||
+ } else {
|
||||
+ keepAliveTime = currentTime; // hijack this field for 1 second intervals
|
||||
+ keepAlives.add(currentTime); // currentTime is ID
|
||||
+ send(new ClientboundKeepAlivePacket(currentTime));
|
||||
+ }
|
||||
+ }
|
||||
+ } else
|
||||
+ // Purpur end
|
||||
+
|
||||
if (this.keepAlivePending) {
|
||||
if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info
|
||||
579
patches/server/0044-Leaves-Protocol-Core.patch
Normal file
@@ -0,0 +1,579 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Sun, 17 Dec 2023 20:39:21 +0800
|
||||
Subject: [PATCH] Leaves Protocol Core
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index 1e3117ccd51be58d988089207a3efdbff02fc374..a28cdeed2a0a2d5194edcfc13cac38f2f2d80489 100644
|
||||
--- a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -313,6 +313,8 @@ public final class RegionizedServer {
|
||||
|
||||
// player list
|
||||
MinecraftServer.getServer().getPlayerList().tick();
|
||||
+
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(); //Leaves
|
||||
}
|
||||
|
||||
private void tickPlayerSample() {
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java b/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
||||
index af86f752c33a2990405fea058b7c41c437ba9d46..bada9fae1e7178162429e1f5a1608b9c4a680a6c 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
||||
@@ -20,7 +20,12 @@ public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implem
|
||||
|
||||
private static CustomPacketPayload readPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
FriendlyByteBuf.Reader<? extends CustomPacketPayload> packetdataserializer_a = (FriendlyByteBuf.Reader) ServerboundCustomPayloadPacket.KNOWN_TYPES.get(id);
|
||||
-
|
||||
+ // Leaves start - protocol
|
||||
+ CustomPacketPayload leavesPayload = top.leavesmc.leaves.protocol.core.LeavesProtocolManager.getPayload(id, buf);
|
||||
+ if (leavesPayload != null) {
|
||||
+ return leavesPayload;
|
||||
+ }
|
||||
+ // Leaves end - protocol
|
||||
return (CustomPacketPayload) (packetdataserializer_a != null ? (CustomPacketPayload) packetdataserializer_a.apply(buf) : readUnknownPayload(id, buf));
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 9d23285f97ac5d90eb177ddc325281fa197d7f76..e1ace2ad411b8d54c56660b41e774a1c998b3ac3 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -127,6 +127,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
@Override
|
||||
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(player, packet.payload()); // Leaves - protocol
|
||||
// Paper start - handle brand payload packet
|
||||
if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.BrandPayload brandPayload) {
|
||||
this.player.clientBrandName = brandPayload.brand();
|
||||
@@ -144,6 +145,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
||||
for (String channel : channels.split("\0")) {
|
||||
this.getCraftPlayer().addChannel(channel);
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleMinecraftRegister(channel, player); // Leaves - protocol
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex);
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 7edaa7558e40942f94c459e9b480ef640146ec6b..3f366ad035ada0ac8170d2925bbfe86b80bd84cb 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -435,6 +435,8 @@ public abstract class PlayerList {
|
||||
//return; // Folia - region threading - must still allow the player to connect, as we must add to chunk map before handling disconnect
|
||||
}
|
||||
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
||||
+
|
||||
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
|
||||
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
@@ -691,6 +693,7 @@ public abstract class PlayerList {
|
||||
return this.remove(entityplayer, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName())));
|
||||
}
|
||||
public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer, net.kyori.adventure.text.Component leaveMessage) {
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(entityplayer); // Leaves - protocol
|
||||
// Paper end
|
||||
ServerLevel worldserver = entityplayer.serverLevel();
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 5fe36cbb14f0f0e9692cfa40381cebdb4e142bbe..ee66241a422acb8920395fd5e41578a966746f5c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -478,6 +478,7 @@ public final class CraftServer implements Server {
|
||||
MapPalette.setMapColorCache(new CraftMapColorCache(this.logger));
|
||||
}
|
||||
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol
|
||||
}
|
||||
|
||||
public boolean getCommandBlockOverride(String command) {
|
||||
@@ -1114,6 +1115,7 @@ public final class CraftServer implements Server {
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
|
||||
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
||||
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
||||
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleServerReload(); // Leaves - protocol
|
||||
|
||||
int pollCount = 0;
|
||||
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..64a1d25973b032e8cab64bbffa6824a131676773
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
||||
@@ -0,0 +1,16 @@
|
||||
+package top.leavesmc.leaves.protocol.core;
|
||||
+
|
||||
+import java.lang.annotation.ElementType;
|
||||
+import java.lang.annotation.Retention;
|
||||
+import java.lang.annotation.RetentionPolicy;
|
||||
+import java.lang.annotation.Target;
|
||||
+
|
||||
+@Target(ElementType.TYPE)
|
||||
+@Retention(RetentionPolicy.RUNTIME)
|
||||
+public @interface LeavesProtocol {
|
||||
+
|
||||
+ String namespace() default "minecraft";
|
||||
+
|
||||
+ String[] namespaces() default {};
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..055f044ce6cef4377f6f577efdbfad0ec9a2d57b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
||||
@@ -0,0 +1,340 @@
|
||||
+package top.leavesmc.leaves.protocol.core;
|
||||
+
|
||||
+import net.minecraft.network.FriendlyByteBuf;
|
||||
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.apache.commons.lang.ArrayUtils;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.io.File;
|
||||
+import java.io.IOException;
|
||||
+import java.lang.reflect.Constructor;
|
||||
+import java.lang.reflect.InvocationTargetException;
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.net.JarURLConnection;
|
||||
+import java.net.URL;
|
||||
+import java.net.URLDecoder;
|
||||
+import java.nio.charset.StandardCharsets;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collections;
|
||||
+import java.util.Enumeration;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.LinkedHashSet;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import java.util.jar.JarEntry;
|
||||
+import java.util.jar.JarFile;
|
||||
+
|
||||
+public class LeavesProtocolManager {
|
||||
+
|
||||
+ private static final Map<LeavesProtocol, Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>>> KNOWN_TYPES = new HashMap<>();
|
||||
+ private static final Map<LeavesProtocol, Map<ProtocolHandler.PayloadReceiver, Method>> KNOW_RECEIVERS = new HashMap<>();
|
||||
+
|
||||
+ private static final List<Method> TICKERS = new ArrayList<>();
|
||||
+ private static final List<Method> PLAYER_JOIN = new ArrayList<>();
|
||||
+ private static final List<Method> PLAYER_LEAVE = new ArrayList<>();
|
||||
+ private static final List<Method> RELOAD_SERVER = new ArrayList<>();
|
||||
+ private static final Map<LeavesProtocol, Map<ProtocolHandler.MinecraftRegister, Method>> MINECRAFT_REGISTER = new HashMap<>();
|
||||
+
|
||||
+ public static void init() {
|
||||
+ for (Class<?> clazz : getClasses("top.leavesmc.leaves.protocol")) {
|
||||
+ final LeavesProtocol protocol = clazz.getAnnotation(LeavesProtocol.class);
|
||||
+ if (protocol != null) {
|
||||
+ Set<Method> methods;
|
||||
+ try {
|
||||
+ Method[] publicMethods = clazz.getMethods();
|
||||
+ Method[] privateMethods = clazz.getDeclaredMethods();
|
||||
+ methods = new HashSet<>(publicMethods.length + privateMethods.length, 1.0f);
|
||||
+ Collections.addAll(methods, publicMethods);
|
||||
+ Collections.addAll(methods, privateMethods);
|
||||
+ } catch (NoClassDefFoundError e) {
|
||||
+ e.printStackTrace();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = new HashMap<>();
|
||||
+ for (final Method method : methods) {
|
||||
+ if (method.isBridge() || method.isSynthetic() || !Modifier.isStatic(method.getModifiers())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ method.setAccessible(true);
|
||||
+
|
||||
+ final ProtocolHandler.Init init = method.getAnnotation(ProtocolHandler.Init.class);
|
||||
+ if (init != null) {
|
||||
+ try {
|
||||
+ method.invoke(null);
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.PayloadReceiver receiver = method.getAnnotation(ProtocolHandler.PayloadReceiver.class);
|
||||
+ if (receiver != null) {
|
||||
+ try {
|
||||
+ map.put(receiver, receiver.payload().getConstructor(ResourceLocation.class, FriendlyByteBuf.class));
|
||||
+ } catch (NoSuchMethodException e) {
|
||||
+ e.printStackTrace();
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!KNOW_RECEIVERS.containsKey(protocol)) {
|
||||
+ KNOW_RECEIVERS.put(protocol, new HashMap<>());
|
||||
+ }
|
||||
+
|
||||
+ KNOW_RECEIVERS.get(protocol).put(receiver, method);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.Ticker ticker = method.getAnnotation(ProtocolHandler.Ticker.class);
|
||||
+ if (ticker != null) {
|
||||
+ TICKERS.add(method);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.PlayerJoin playerJoin = method.getAnnotation(ProtocolHandler.PlayerJoin.class);
|
||||
+ if (playerJoin != null) {
|
||||
+ PLAYER_JOIN.add(method);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.PlayerLeave playerLeave = method.getAnnotation(ProtocolHandler.PlayerLeave.class);
|
||||
+ if (playerLeave != null) {
|
||||
+ PLAYER_LEAVE.add(method);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.ReloadServer reloadServer = method.getAnnotation(ProtocolHandler.ReloadServer.class);
|
||||
+ if (reloadServer != null) {
|
||||
+ RELOAD_SERVER.add(method);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final ProtocolHandler.MinecraftRegister minecraftRegister = method.getAnnotation(ProtocolHandler.MinecraftRegister.class);
|
||||
+ if (minecraftRegister != null) {
|
||||
+ if (!MINECRAFT_REGISTER.containsKey(protocol)) {
|
||||
+ MINECRAFT_REGISTER.put(protocol, new HashMap<>());
|
||||
+ }
|
||||
+
|
||||
+ MINECRAFT_REGISTER.get(protocol).put(minecraftRegister, method);
|
||||
+ }
|
||||
+ }
|
||||
+ KNOWN_TYPES.put(protocol, map);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static CustomPacketPayload getPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
+ for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) {
|
||||
+ if (!protocol.namespace().equals(id.getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), id.getNamespace())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = KNOWN_TYPES.get(protocol);
|
||||
+ for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
||||
+ if (receiver.ignoreId() || receiver.payloadId().equals(id.getPath()) || ArrayUtils.contains(receiver.payloadIds(), id.getPath())) {
|
||||
+ try {
|
||||
+ return map.get(receiver).newInstance(id, buf);
|
||||
+ } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ public static void handlePayload(ServerPlayer player, CustomPacketPayload payload) {
|
||||
+ for (LeavesProtocol protocol : KNOW_RECEIVERS.keySet()) {
|
||||
+ if (!protocol.namespace().equals(payload.id().getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), payload.id().getNamespace())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Map<ProtocolHandler.PayloadReceiver, Method> map = KNOW_RECEIVERS.get(protocol);
|
||||
+ for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
||||
+ if (payload.getClass() == receiver.payload()) {
|
||||
+ if (receiver.ignoreId() || receiver.payloadId().equals(payload.id().getPath()) ||
|
||||
+ ArrayUtils.contains(receiver.payloadIds(), payload.id().getPath())) {
|
||||
+ try {
|
||||
+ map.get(receiver).invoke(null, player, payload);
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void handleTick() {
|
||||
+ if (!TICKERS.isEmpty()) {
|
||||
+ try {
|
||||
+ for (Method method : TICKERS) {
|
||||
+ method.invoke(null);
|
||||
+ }
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void handlePlayerJoin(ServerPlayer player) {
|
||||
+ if (!PLAYER_JOIN.isEmpty()) {
|
||||
+ try {
|
||||
+ for (Method method : PLAYER_JOIN) {
|
||||
+ method.invoke(null, player);
|
||||
+ }
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void handlePlayerLeave(ServerPlayer player) {
|
||||
+ if (!PLAYER_LEAVE.isEmpty()) {
|
||||
+ try {
|
||||
+ for (Method method : PLAYER_LEAVE) {
|
||||
+ method.invoke(null, player);
|
||||
+ }
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void handleServerReload() {
|
||||
+ if (!RELOAD_SERVER.isEmpty()) {
|
||||
+ try {
|
||||
+ for (Method method : RELOAD_SERVER) {
|
||||
+ method.invoke(null);
|
||||
+ }
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void handleMinecraftRegister(String channelId, ServerPlayer player) {
|
||||
+ for (LeavesProtocol protocol : MINECRAFT_REGISTER.keySet()) {
|
||||
+ String[] channel = channelId.split(":");
|
||||
+ if (!protocol.namespace().equals(channel[0]) && !ArrayUtils.contains(protocol.namespaces(), channel[0])) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Map<ProtocolHandler.MinecraftRegister, Method> map = MINECRAFT_REGISTER.get(protocol);
|
||||
+ for (ProtocolHandler.MinecraftRegister register : map.keySet()) {
|
||||
+ if (register.ignoreId() || register.channelId().equals(channel[1]) ||
|
||||
+ ArrayUtils.contains(register.channelIds(), channel[1])) {
|
||||
+ try {
|
||||
+ map.get(register).invoke(null, player);
|
||||
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static Set<Class<?>> getClasses(String pack) {
|
||||
+ Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
|
||||
+ String packageDirName = pack.replace('.', '/');
|
||||
+ Enumeration<URL> dirs;
|
||||
+ try {
|
||||
+ dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
|
||||
+ while (dirs.hasMoreElements()) {
|
||||
+ URL url = dirs.nextElement();
|
||||
+ String protocol = url.getProtocol();
|
||||
+ if ("file".equals(protocol)) {
|
||||
+ String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8);
|
||||
+ findClassesInPackageByFile(pack, filePath, classes);
|
||||
+ } else if ("jar".equals(protocol)) {
|
||||
+ JarFile jar;
|
||||
+ try {
|
||||
+ jar = ((JarURLConnection) url.openConnection()).getJarFile();
|
||||
+ Enumeration<JarEntry> entries = jar.entries();
|
||||
+ findClassesInPackageByJar(pack, entries, packageDirName, classes);
|
||||
+ } catch (IOException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (IOException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ return classes;
|
||||
+ }
|
||||
+
|
||||
+ private static void findClassesInPackageByFile(String packageName, String packagePath, Set<Class<?>> classes) {
|
||||
+ File dir = new File(packagePath);
|
||||
+ if (!dir.exists() || !dir.isDirectory()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ File[] dirfiles = dir.listFiles((file) -> file.isDirectory() || file.getName().endsWith(".class"));
|
||||
+ if (dirfiles != null) {
|
||||
+ for (File file : dirfiles) {
|
||||
+ if (file.isDirectory()) {
|
||||
+ findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), classes);
|
||||
+ } else {
|
||||
+ String className = file.getName().substring(0, file.getName().length() - 6);
|
||||
+ try {
|
||||
+ classes.add(Class.forName(packageName + '.' + className));
|
||||
+ } catch (ClassNotFoundException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, Set<Class<?>> classes) {
|
||||
+ while (entries.hasMoreElements()) {
|
||||
+ JarEntry entry = entries.nextElement();
|
||||
+ String name = entry.getName();
|
||||
+ if (name.charAt(0) == '/') {
|
||||
+ name = name.substring(1);
|
||||
+ }
|
||||
+ if (name.startsWith(packageDirName)) {
|
||||
+ int idx = name.lastIndexOf('/');
|
||||
+ if (idx != -1) {
|
||||
+ packageName = name.substring(0, idx).replace('/', '.');
|
||||
+ }
|
||||
+ if (name.endsWith(".class") && !entry.isDirectory()) {
|
||||
+ String className = name.substring(packageName.length() + 1, name.length() - 6);
|
||||
+ try {
|
||||
+ classes.add(Class.forName(packageName + '.' + className));
|
||||
+ } catch (ClassNotFoundException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record EmptyPayload(ResourceLocation id) implements CustomPacketPayload {
|
||||
+
|
||||
+ public EmptyPayload(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
+ this(location);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(@NotNull FriendlyByteBuf buf) {
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record LeavesPayload(FriendlyByteBuf data, ResourceLocation id) implements CustomPacketPayload {
|
||||
+
|
||||
+ public LeavesPayload(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
+ this(new FriendlyByteBuf(buf.readBytes(buf.readableBytes())), location);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(FriendlyByteBuf buf) {
|
||||
+ buf.writeBytes(data);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d696f001d2576d1b61cc732c81f22eb52205072b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
||||
@@ -0,0 +1,65 @@
|
||||
+package top.leavesmc.leaves.protocol.core;
|
||||
+
|
||||
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
+
|
||||
+import java.lang.annotation.ElementType;
|
||||
+import java.lang.annotation.Retention;
|
||||
+import java.lang.annotation.RetentionPolicy;
|
||||
+import java.lang.annotation.Target;
|
||||
+
|
||||
+public class ProtocolHandler {
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface Init {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface PayloadReceiver {
|
||||
+
|
||||
+ Class<? extends CustomPacketPayload> payload();
|
||||
+
|
||||
+ String[] payloadIds() default {};
|
||||
+
|
||||
+ String payloadId() default "";
|
||||
+
|
||||
+ boolean ignoreId() default false;
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface Ticker {
|
||||
+ int delay() default 0;
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface PlayerJoin {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface PlayerLeave {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface ReloadServer {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @Target(ElementType.METHOD)
|
||||
+ @Retention(RetentionPolicy.RUNTIME)
|
||||
+ public @interface MinecraftRegister {
|
||||
+
|
||||
+ String channelId() default "";
|
||||
+
|
||||
+ String[] channelIds() default {};
|
||||
+
|
||||
+ boolean ignoreId() default false;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5282c5ad3d26d06ab685ddaaf6fd9a4d49559717
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java
|
||||
@@ -0,0 +1,36 @@
|
||||
+package top.leavesmc.leaves.protocol.core;
|
||||
+
|
||||
+import net.minecraft.network.FriendlyByteBuf;
|
||||
+import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
|
||||
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.function.Consumer;
|
||||
+
|
||||
+public class ProtocolUtils {
|
||||
+
|
||||
+ public static void sendEmptyPayloadPacket(ServerPlayer player, ResourceLocation id) {
|
||||
+ player.connection.send(new ClientboundCustomPayloadPacket(new LeavesProtocolManager.EmptyPayload(id)));
|
||||
+ }
|
||||
+
|
||||
+ public static void sendPayloadPacket(ServerPlayer player, ResourceLocation id, Consumer<FriendlyByteBuf> consumer) {
|
||||
+ player.connection.send(new ClientboundCustomPayloadPacket(new CustomPacketPayload() {
|
||||
+ @Override
|
||||
+ public void write(@NotNull FriendlyByteBuf buf) {
|
||||
+ consumer.accept(buf);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public ResourceLocation id() {
|
||||
+ return id;
|
||||
+ }
|
||||
+ }));
|
||||
+ }
|
||||
+
|
||||
+ public static void sendPayloadPacket(ServerPlayer player, CustomPacketPayload payload) {
|
||||
+ player.connection.send(new ClientboundCustomPayloadPacket(payload));
|
||||
+ }
|
||||
+}
|
||||
709
patches/server/0045-Leaves-PCA-sync-protocol.patch
Normal file
@@ -0,0 +1,709 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Sun, 17 Dec 2023 21:01:59 +0800
|
||||
Subject: [PATCH] Leaves PCA sync protocol
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index a62680768068b611fe723fedeb617d42c643e59e..cfe9a8eb705039ee7e2dc9262e1355c4b0f664bb 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -66,6 +66,10 @@ public class LuminolConfig {
|
||||
public static boolean enableAsyncMobSpawning = false;
|
||||
public static boolean useAlternateKeepAlive = false;
|
||||
|
||||
+ public static boolean pcaSyncProtocol = false;
|
||||
+ public static String pcaSyncPlayerEntity = "NOBODY";
|
||||
+
|
||||
+
|
||||
public static void init() throws IOException {
|
||||
PARENT_FOLDER.mkdir();
|
||||
|
||||
@@ -194,6 +198,9 @@ public class LuminolConfig {
|
||||
enableAsyncMobSpawning = get("optimizations.enable_async_mob_spawning",enableAsyncMobSpawning);
|
||||
RegionizedWorldData.initMobSpawningExecutor();
|
||||
useAlternateKeepAlive = get("optimizations.enable_alternative_keep_alive_handling",useAlternateKeepAlive,"Enabling this sends a keepalive packet once per second to a player, and only kicks for timeout if none of them were responded to in 30 seconds. Responding to any of them in any order will keep the player connected. AKA, it won't kick your players because one packet gets dropped somewhere along the lines(From purpur)");
|
||||
+
|
||||
+ pcaSyncProtocol = get("gameplay.enable_pca_sync_protocol",pcaSyncProtocol);
|
||||
+ pcaSyncPlayerEntity = get("gameplay.pca_sync_player_entity",pcaSyncPlayerEntity,"Available values: NOBODY,EVERYBODY,OPS,OPS_AND_SELF");
|
||||
}
|
||||
|
||||
public static <T> T get(String key,T def){
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
index a0628b9d74c29d02bfba583edf7ee6f2cde2cff6..698c7bfddb0d45d088c30fd26eccb86b924fd60a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
@@ -373,6 +373,11 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
||||
|
||||
@Override
|
||||
public void containerChanged(Container sender) {
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
boolean flag = this.isSaddled();
|
||||
|
||||
this.updateContainerEquipment();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
index ce728f062794e239d1dfdf842d7d0c725f77fba7..a3200593788525c7f18420036044bfdccfaf40fc 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
||||
@@ -64,6 +64,15 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
|
||||
super(type, world);
|
||||
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F);
|
||||
this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F);
|
||||
+ // Leaves start - pca
|
||||
+ if (!this.level().isClientSide()) {
|
||||
+ this.inventory.addListener(inventory -> {
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
index f64edfdb03f99624daf1e05b5dc86d845c3018b6..e98ea5f93a829e232a61eee4564209d1831f8b8d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
||||
@@ -138,7 +138,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void setChanged() {}
|
||||
+ public void setChanged() {
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+ }
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index a18aadbf7ae83713e1f2b21553185d8000bc7699..4b174bed02fb98f798f9444e03fc866baf1e1a07 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -569,6 +569,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
public boolean stillValid(net.minecraft.world.entity.player.Player player) {
|
||||
return Container.stillValidBlockEntity(this, player);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index 416aa989ebb18a8741cc9d605a1180ab830f6643..b73c3dc28a95279285e911bfed3bc3d3f038e6db 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -131,6 +131,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
||||
this.items = list;
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
protected Component getDefaultName() {
|
||||
return Component.translatable("container.barrel");
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
index cf09525efd2d53bf884cd6ec3b0b9229715895eb..9c7b5fbec4ec1eb6b39f139a9b16483208249b6f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
+import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -127,6 +128,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
super.setChanged();
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -188,6 +194,12 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, this.getBlockState()));
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
entity.discard();
|
||||
super.setChanged();
|
||||
}
|
||||
@@ -334,6 +346,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, flowerPos)) {
|
||||
flag = true;
|
||||
iterator.remove();
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(Objects.requireNonNull(world.getBlockEntity(pos)));
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
// CraftBukkit start
|
||||
} else {
|
||||
tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - use exitTickCounter to keep actual bee life
|
||||
@@ -385,6 +402,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
||||
this.maxBees = nbt.getInt("Bukkit.MaxEntities");
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
index 526d1bfd5ad0de7bcfd0c2da902515f3dec94c54..66758af67aca2c726b2f5b451f3f7197102af22f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -333,6 +333,16 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return Container.stillValidBlockEntity(this, player);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index d66806565770cb03a21794f99e5c4b0f3040b26a..034bc37a8b50a3c9904f4f53c8758b1b02b458b1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -220,6 +220,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
// Pufferfish end
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
public float getOpenNess(float tickDelta) {
|
||||
return this.chestLidController.getOpenness(tickDelta);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
index 881379681c39230a00b3a1f11cd87498984396c7..51fae4d72eed9e4224a8abe1a0b6520835857ba5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
@@ -92,6 +92,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity {
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
protected Component getDefaultName() {
|
||||
return Component.translatable("container.dispenser");
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index c90d578643490709936545ee9cbd41c8671eeb7a..3527a3cc76d3b1ad1319f1eebe31fd4d9e8aa039 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -155,6 +155,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
protected Component getDefaultName() {
|
||||
return Component.translatable("container.hopper");
|
||||
@@ -234,6 +244,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (flag) {
|
||||
blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
||||
setChanged(world, pos, state);
|
||||
+ // Leaves start - pca
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(blockEntity);
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
return true;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
index 1fa22445a4ecc8c08dbcf0cc6bd39dc5003604c4..c1492fce06cdc00a8e82977f0c474a541efa39e8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
@@ -269,6 +269,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
||||
this.itemStacks = list;
|
||||
}
|
||||
|
||||
+ // Leaves start - pca
|
||||
+ @Override
|
||||
+ public void setChanged() {
|
||||
+ super.setChanged();
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - pca
|
||||
+
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction side) {
|
||||
return ShulkerBoxBlockEntity.SLOTS;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
index b23e43f7ac22bc106a0bcde4a8bca9ecba1a9ae4..08bf4f13e0ee6698b18a6946cb78adb4ae65c852 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
@@ -45,7 +45,7 @@ import org.bukkit.scheduler.BukkitWorker;
|
||||
*/
|
||||
public class CraftScheduler implements BukkitScheduler {
|
||||
|
||||
- static Plugin MINECRAFT = new MinecraftInternalPlugin();
|
||||
+ public static Plugin MINECRAFT = new MinecraftInternalPlugin();
|
||||
/**
|
||||
* The start ID for the counter.
|
||||
*/
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ebd28033ddf0fe6a354585dc2818a9b481d90ed4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
||||
@@ -0,0 +1,384 @@
|
||||
+package top.leavesmc.leaves.protocol;
|
||||
+
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.network.FriendlyByteBuf;
|
||||
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import net.minecraft.world.entity.Entity;
|
||||
+import net.minecraft.world.entity.player.Player;
|
||||
+import net.minecraft.world.level.Level;
|
||||
+import net.minecraft.world.level.block.ChestBlock;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.state.BlockState;
|
||||
+import net.minecraft.world.level.block.state.properties.ChestType;
|
||||
+import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
+import org.apache.commons.lang3.tuple.MutablePair;
|
||||
+import org.apache.commons.lang3.tuple.Pair;
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.bukkit.craftbukkit.scheduler.CraftScheduler;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+import top.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
+
|
||||
+import java.util.HashMap;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import java.util.concurrent.locks.ReentrantLock;
|
||||
+
|
||||
+import static org.bukkit.craftbukkit.scheduler.CraftScheduler.MINECRAFT;
|
||||
+import static top.leavesmc.leaves.protocol.core.LeavesProtocolManager.EmptyPayload;
|
||||
+
|
||||
+@LeavesProtocol(namespace = "pca")
|
||||
+public class PcaSyncProtocol {
|
||||
+
|
||||
+ public static final String PROTOCOL_ID = "pca";
|
||||
+
|
||||
+ public static final ReentrantLock lock = new ReentrantLock(true);
|
||||
+ public static final ReentrantLock pairLock = new ReentrantLock(true);
|
||||
+
|
||||
+ // send
|
||||
+ private static final ResourceLocation ENABLE_PCA_SYNC_PROTOCOL = id("enable_pca_sync_protocol");
|
||||
+ private static final ResourceLocation DISABLE_PCA_SYNC_PROTOCOL = id("disable_pca_sync_protocol");
|
||||
+ private static final ResourceLocation UPDATE_ENTITY = id("update_entity");
|
||||
+ private static final ResourceLocation UPDATE_BLOCK_ENTITY = id("update_block_entity");
|
||||
+
|
||||
+ private static final Map<ServerPlayer, Pair<ResourceLocation, BlockPos>> playerWatchBlockPos = new HashMap<>();
|
||||
+ private static final Map<ServerPlayer, Pair<ResourceLocation, Entity>> playerWatchEntity = new HashMap<>();
|
||||
+ private static final Map<Pair<ResourceLocation, BlockPos>, Set<ServerPlayer>> blockPosWatchPlayerSet = new HashMap<>();
|
||||
+ private static final Map<Pair<ResourceLocation, Entity>, Set<ServerPlayer>> entityWatchPlayerSet = new HashMap<>();
|
||||
+ private static final MutablePair<ResourceLocation, Entity> ResourceLocationEntityPair = new MutablePair<>();
|
||||
+ private static final MutablePair<ResourceLocation, BlockPos> ResourceLocationBlockPosPair = new MutablePair<>();
|
||||
+
|
||||
+ @Contract("_ -> new")
|
||||
+ public static @NotNull ResourceLocation id(String path) {
|
||||
+ return new ResourceLocation(PROTOCOL_ID, path);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PlayerJoin
|
||||
+ private static void onJoin(ServerPlayer player) {
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ enablePcaSyncProtocol(player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.ReloadServer
|
||||
+ private static void onServerReload() {
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ enablePcaSyncProtocolGlobal();
|
||||
+ } else {
|
||||
+ disablePcaSyncProtocolGlobal();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = EmptyPayload.class, payloadId = "cancel_sync_block_entity")
|
||||
+ private static void cancelSyncBlockEntityHandler(ServerPlayer player, EmptyPayload payload) {
|
||||
+ if (!me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ return;
|
||||
+ }
|
||||
+ PcaSyncProtocol.clearPlayerWatchBlock(player);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = EmptyPayload.class, payloadId = "cancel_sync_entity")
|
||||
+ private static void cancelSyncEntityHandler(ServerPlayer player, EmptyPayload payload) {
|
||||
+ if (!me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ return;
|
||||
+ }
|
||||
+ PcaSyncProtocol.clearPlayerWatchEntity(player);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = SyncBlockEntityPayload.class, payloadId = "sync_block_entity")
|
||||
+ private static void syncBlockEntityHandler(ServerPlayer player, SyncBlockEntityPayload payload) {
|
||||
+ if (!me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ return;
|
||||
+ }
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ BlockPos pos = payload.pos;
|
||||
+ ServerLevel world = player.serverLevel();
|
||||
+
|
||||
+ player.getBukkitEntity().getScheduler().execute(MINECRAFT,() -> {
|
||||
+ BlockState blockState = world.getBlockState(pos);
|
||||
+ clearPlayerWatchData(player);
|
||||
+
|
||||
+ BlockEntity blockEntityAdj = null;
|
||||
+ if (blockState.getBlock() instanceof ChestBlock) {
|
||||
+ if (blockState.getValue(ChestBlock.TYPE) != ChestType.SINGLE) {
|
||||
+ BlockPos posAdj = pos.offset(ChestBlock.getConnectedDirection(blockState).getNormal());
|
||||
+ // The method in World now checks that the caller is from the same thread...
|
||||
+ blockEntityAdj = world.getChunk(posAdj).getBlockEntity(posAdj);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (blockEntityAdj != null) {
|
||||
+ updateBlockEntity(player, blockEntityAdj);
|
||||
+ }
|
||||
+
|
||||
+ // The method in World now checks that the caller is from the same thread...
|
||||
+ BlockEntity blockEntity = world.getChunk(pos).getBlockEntity(pos);
|
||||
+ if (blockEntity != null) {
|
||||
+ updateBlockEntity(player, blockEntity);
|
||||
+ }
|
||||
+
|
||||
+ Pair<ResourceLocation, BlockPos> pair = new ImmutablePair<>(player.level().dimension().location(), pos);
|
||||
+ lock.lock();
|
||||
+ playerWatchBlockPos.put(player, pair);
|
||||
+ if (!blockPosWatchPlayerSet.containsKey(pair)) {
|
||||
+ blockPosWatchPlayerSet.put(pair, new HashSet<>());
|
||||
+ }
|
||||
+ blockPosWatchPlayerSet.get(pair).add(player);
|
||||
+ lock.unlock();
|
||||
+ },null,1);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = SyncEntityPayload.class, payloadId = "sync_entity")
|
||||
+ private static void syncEntityHandler(ServerPlayer player, SyncEntityPayload payload) {
|
||||
+ if (!me.earthme.luminol.LuminolConfig.pcaSyncProtocol) {
|
||||
+ return;
|
||||
+ }
|
||||
+ MinecraftServer server = MinecraftServer.getServer();
|
||||
+ int entityId = payload.entityId;
|
||||
+ ServerLevel world = player.serverLevel();
|
||||
+ player.getBukkitEntity().getScheduler().execute(MINECRAFT,() -> {
|
||||
+ Entity entity = world.getEntity(entityId);
|
||||
+ if (entity != null) {
|
||||
+ clearPlayerWatchData(player);
|
||||
+ if (entity instanceof Player) {
|
||||
+ if (me.earthme.luminol.LuminolConfig.pcaSyncPlayerEntity.equals("NOBODY")) {
|
||||
+ return;
|
||||
+ }else if (me.earthme.luminol.LuminolConfig.pcaSyncPlayerEntity.equals("OPS")) {
|
||||
+ if (server.getProfilePermissions(player.getGameProfile()) < 2) {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (me.earthme.luminol.LuminolConfig.pcaSyncPlayerEntity.equals("OPS_AND_SELF")) {
|
||||
+ if (server.getProfilePermissions(player.getGameProfile()) < 2 &&
|
||||
+ entity != player) {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (!me.earthme.luminol.LuminolConfig.pcaSyncPlayerEntity.equals("EVERYONE")) {
|
||||
+ // wtf????
|
||||
+ LogManager.getLogger().warn("pcaSyncPlayerEntity wtf???");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ updateEntity(player, entity);
|
||||
+
|
||||
+ Pair<ResourceLocation, Entity> pair = new ImmutablePair<>(entity.level().dimension().location(), entity);
|
||||
+ lock.lock();
|
||||
+ playerWatchEntity.put(player, pair);
|
||||
+ if (!entityWatchPlayerSet.containsKey(pair)) {
|
||||
+ entityWatchPlayerSet.put(pair, new HashSet<>());
|
||||
+ }
|
||||
+ entityWatchPlayerSet.get(pair).add(player);
|
||||
+ lock.unlock();
|
||||
+ }
|
||||
+ },null,1);
|
||||
+ }
|
||||
+
|
||||
+ public static void enablePcaSyncProtocol(@NotNull ServerPlayer player) {
|
||||
+ ProtocolUtils.sendEmptyPayloadPacket(player, ENABLE_PCA_SYNC_PROTOCOL);
|
||||
+ }
|
||||
+
|
||||
+ public static void disablePcaSyncProtocol(@NotNull ServerPlayer player) {
|
||||
+ ProtocolUtils.sendEmptyPayloadPacket(player, DISABLE_PCA_SYNC_PROTOCOL);
|
||||
+ }
|
||||
+
|
||||
+ public static void updateEntity(@NotNull ServerPlayer player, @NotNull Entity entity) {
|
||||
+ CompoundTag nbt = entity.saveWithoutId(new CompoundTag());
|
||||
+ ProtocolUtils.sendPayloadPacket(player, UPDATE_ENTITY, buf -> {
|
||||
+ buf.writeResourceLocation(entity.level().dimension().location());
|
||||
+ buf.writeInt(entity.getId());
|
||||
+ buf.writeNbt(nbt);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public static void updateBlockEntity(@NotNull ServerPlayer player, @NotNull BlockEntity blockEntity) {
|
||||
+ Level world = blockEntity.getLevel();
|
||||
+
|
||||
+ if (world == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ProtocolUtils.sendPayloadPacket(player, UPDATE_BLOCK_ENTITY, buf -> {
|
||||
+ buf.writeResourceLocation(world.dimension().location());
|
||||
+ buf.writeBlockPos(blockEntity.getBlockPos());
|
||||
+ buf.writeNbt(blockEntity.saveWithId());
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private static MutablePair<ResourceLocation, Entity> getResourceLocationEntityPair(ResourceLocation ResourceLocation, Entity entity) {
|
||||
+ pairLock.lock();
|
||||
+ ResourceLocationEntityPair.setLeft(ResourceLocation);
|
||||
+ ResourceLocationEntityPair.setRight(entity);
|
||||
+ pairLock.unlock();
|
||||
+ return ResourceLocationEntityPair;
|
||||
+ }
|
||||
+
|
||||
+ private static MutablePair<ResourceLocation, BlockPos> getResourceLocationBlockPosPair(ResourceLocation ResourceLocation, BlockPos pos) {
|
||||
+ pairLock.lock();
|
||||
+ ResourceLocationBlockPosPair.setLeft(ResourceLocation);
|
||||
+ ResourceLocationBlockPosPair.setRight(pos);
|
||||
+ pairLock.unlock();
|
||||
+ return ResourceLocationBlockPosPair;
|
||||
+ }
|
||||
+
|
||||
+ private static @Nullable Set<ServerPlayer> getWatchPlayerList(@NotNull Entity entity) {
|
||||
+ return entityWatchPlayerSet.get(getResourceLocationEntityPair(entity.level().dimension().location(), entity));
|
||||
+ }
|
||||
+
|
||||
+ private static @Nullable Set<ServerPlayer> getWatchPlayerList(@NotNull Level world, @NotNull BlockPos blockPos) {
|
||||
+ return blockPosWatchPlayerSet.get(getResourceLocationBlockPosPair(world.dimension().location(), blockPos));
|
||||
+ }
|
||||
+
|
||||
+ public static boolean syncEntityToClient(@NotNull Entity entity) {
|
||||
+ if (entity.level().isClientSide()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ lock.lock();
|
||||
+ Set<ServerPlayer> playerList = getWatchPlayerList(entity);
|
||||
+ boolean ret = false;
|
||||
+ if (playerList != null) {
|
||||
+ for (ServerPlayer player : playerList) {
|
||||
+ updateEntity(player, entity);
|
||||
+ ret = true;
|
||||
+ }
|
||||
+ }
|
||||
+ lock.unlock();
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean syncBlockEntityToClient(@NotNull BlockEntity blockEntity) {
|
||||
+ boolean ret = false;
|
||||
+ Level world = blockEntity.getLevel();
|
||||
+ BlockPos pos = blockEntity.getBlockPos();
|
||||
+ if (world != null) {
|
||||
+ if (world.isClientSide()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ BlockState blockState = world.getBlockState(pos);
|
||||
+ lock.lock();
|
||||
+ Set<ServerPlayer> playerList = getWatchPlayerList(world, blockEntity.getBlockPos());
|
||||
+
|
||||
+ Set<ServerPlayer> playerListAdj = null;
|
||||
+
|
||||
+ if (blockState.getBlock() instanceof ChestBlock) {
|
||||
+ if (blockState.getValue(ChestBlock.TYPE) != ChestType.SINGLE) {
|
||||
+ BlockPos posAdj = pos.offset(ChestBlock.getConnectedDirection(blockState).getNormal());
|
||||
+ playerListAdj = getWatchPlayerList(world, posAdj);
|
||||
+ }
|
||||
+ }
|
||||
+ if (playerListAdj != null) {
|
||||
+ if (playerList == null) {
|
||||
+ playerList = playerListAdj;
|
||||
+ } else {
|
||||
+ playerList.addAll(playerListAdj);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (playerList != null) {
|
||||
+ for (ServerPlayer player : playerList) {
|
||||
+ updateBlockEntity(player, blockEntity);
|
||||
+ ret = true;
|
||||
+ }
|
||||
+ }
|
||||
+ lock.unlock();
|
||||
+ }
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ private static void clearPlayerWatchEntity(ServerPlayer player) {
|
||||
+ lock.lock();
|
||||
+ Pair<ResourceLocation, Entity> pair = playerWatchEntity.get(player);
|
||||
+ if (pair != null) {
|
||||
+ Set<ServerPlayer> playerSet = entityWatchPlayerSet.get(pair);
|
||||
+ playerSet.remove(player);
|
||||
+ if (playerSet.isEmpty()) {
|
||||
+ entityWatchPlayerSet.remove(pair);
|
||||
+ }
|
||||
+ playerWatchEntity.remove(player);
|
||||
+ }
|
||||
+ lock.unlock();
|
||||
+ }
|
||||
+
|
||||
+ private static void clearPlayerWatchBlock(ServerPlayer player) {
|
||||
+ lock.lock();
|
||||
+ Pair<ResourceLocation, BlockPos> pair = playerWatchBlockPos.get(player);
|
||||
+ if (pair != null) {
|
||||
+ Set<ServerPlayer> playerSet = blockPosWatchPlayerSet.get(pair);
|
||||
+ playerSet.remove(player);
|
||||
+ if (playerSet.isEmpty()) {
|
||||
+ blockPosWatchPlayerSet.remove(pair);
|
||||
+ }
|
||||
+ playerWatchBlockPos.remove(player);
|
||||
+ }
|
||||
+ lock.unlock();
|
||||
+ }
|
||||
+
|
||||
+ public static void disablePcaSyncProtocolGlobal() {
|
||||
+ lock.lock();
|
||||
+ playerWatchBlockPos.clear();
|
||||
+ playerWatchEntity.clear();
|
||||
+ blockPosWatchPlayerSet.clear();
|
||||
+ entityWatchPlayerSet.clear();
|
||||
+ lock.unlock();
|
||||
+ for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
||||
+ disablePcaSyncProtocol(player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void enablePcaSyncProtocolGlobal() {
|
||||
+ for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
||||
+ enablePcaSyncProtocol(player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ public static void clearPlayerWatchData(ServerPlayer player) {
|
||||
+ PcaSyncProtocol.clearPlayerWatchBlock(player);
|
||||
+ PcaSyncProtocol.clearPlayerWatchEntity(player);
|
||||
+ }
|
||||
+
|
||||
+ public record SyncBlockEntityPayload(BlockPos pos) implements CustomPacketPayload {
|
||||
+
|
||||
+ public static final ResourceLocation SYNC_BLOCK_ENTITY = PcaSyncProtocol.id("sync_block_entity");
|
||||
+
|
||||
+ public SyncBlockEntityPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
+ this(buf.readBlockPos());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(FriendlyByteBuf buf) {
|
||||
+ buf.writeBlockPos(pos);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ResourceLocation id() {
|
||||
+ return SYNC_BLOCK_ENTITY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record SyncEntityPayload(int entityId) implements CustomPacketPayload {
|
||||
+
|
||||
+ public static final ResourceLocation SYNC_ENTITY = PcaSyncProtocol.id("sync_entity");
|
||||
+
|
||||
+ public SyncEntityPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
+ this(buf.readInt());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(FriendlyByteBuf buf) {
|
||||
+ buf.writeInt(entityId);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull ResourceLocation id() {
|
||||
+ return SYNC_ENTITY;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
183
patches/server/0046-Leaves-Bladeren-protocol.patch
Normal file
@@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Thu, 21 Dec 2023 19:50:41 +0800
|
||||
Subject: [PATCH] Leaves Bladeren protocol
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index cfe9a8eb705039ee7e2dc9262e1355c4b0f664bb..a0fd4fec133617893487586fd52e3a3a864871b4 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -68,6 +68,7 @@ public class LuminolConfig {
|
||||
|
||||
public static boolean pcaSyncProtocol = false;
|
||||
public static String pcaSyncPlayerEntity = "NOBODY";
|
||||
+ public static boolean bladerenLeavesProtocol = false;
|
||||
|
||||
|
||||
public static void init() throws IOException {
|
||||
@@ -201,6 +202,7 @@ public class LuminolConfig {
|
||||
|
||||
pcaSyncProtocol = get("gameplay.enable_pca_sync_protocol",pcaSyncProtocol);
|
||||
pcaSyncPlayerEntity = get("gameplay.pca_sync_player_entity",pcaSyncPlayerEntity,"Available values: NOBODY,EVERYBODY,OPS,OPS_AND_SELF");
|
||||
+ bladerenLeavesProtocol = get("gameplay.bladeren_leaves_protocol",bladerenLeavesProtocol);
|
||||
}
|
||||
|
||||
public static <T> T get(String key,T def){
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..cf344ad5e928f1bf23953d7b25c4636734da69e6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java
|
||||
@@ -0,0 +1,151 @@
|
||||
+package top.leavesmc.leaves.protocol.bladeren;
|
||||
+
|
||||
+import com.google.common.collect.Maps;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.network.FriendlyByteBuf;
|
||||
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
+import top.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
+
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Map;
|
||||
+import java.util.function.BiConsumer;
|
||||
+
|
||||
+@LeavesProtocol(namespace = "bladeren")
|
||||
+public class BladerenProtocol {
|
||||
+
|
||||
+ public static final String PROTOCOL_ID = "bladeren";
|
||||
+ public static final String PROTOCOL_VERSION = "1.0.0";
|
||||
+
|
||||
+ private static final ResourceLocation HELLO_ID = id("hello");
|
||||
+ private static final ResourceLocation FEATURE_MODIFY_ID = id("feature_modify");
|
||||
+
|
||||
+ private static final Map<String, BiConsumer<ServerPlayer, CompoundTag>> registeredFeatures = Maps.newConcurrentMap();
|
||||
+
|
||||
+ @Contract("_ -> new")
|
||||
+ public static @NotNull ResourceLocation id(String path) {
|
||||
+ return new ResourceLocation(PROTOCOL_ID, path);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = BladerenHelloPayload.class, payloadId = "hello")
|
||||
+ private static void handleHello(@NotNull ServerPlayer player, @NotNull BladerenHelloPayload payload) {
|
||||
+ if (LuminolConfig.bladerenLeavesProtocol) {
|
||||
+ String clientVersion = payload.version;
|
||||
+ CompoundTag tag = payload.nbt;
|
||||
+
|
||||
+ if (tag != null) {
|
||||
+ CompoundTag featureNbt = tag.getCompound("Features");
|
||||
+ for (String name : featureNbt.getAllKeys()) {
|
||||
+
|
||||
+ final BiConsumer<ServerPlayer,CompoundTag> target = registeredFeatures.get(name);
|
||||
+
|
||||
+ if (target != null){
|
||||
+ target.accept(player, featureNbt.getCompound(name));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = BladerenFeatureModifyPayload.class, payloadId = "feature_modify")
|
||||
+ private static void handleModify(@NotNull ServerPlayer player, @NotNull BladerenFeatureModifyPayload payload) {
|
||||
+ if (LuminolConfig.bladerenLeavesProtocol) {
|
||||
+ String name = payload.name;
|
||||
+ CompoundTag tag = payload.nbt;
|
||||
+
|
||||
+ final BiConsumer<ServerPlayer,CompoundTag> target = registeredFeatures.get(name);
|
||||
+
|
||||
+ if (target != null){
|
||||
+ target.accept(player, tag);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PlayerJoin
|
||||
+ public static void onPlayerJoin(@NotNull ServerPlayer player) {
|
||||
+ if (LuminolConfig.bladerenLeavesProtocol) {
|
||||
+ CompoundTag tag = new CompoundTag();
|
||||
+ LeavesFeatureSet.writeNBT(tag);
|
||||
+ ProtocolUtils.sendPayloadPacket(player, new BladerenHelloPayload(PROTOCOL_VERSION, tag));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void registerFeature(String name, BiConsumer<ServerPlayer, CompoundTag> consumer) {
|
||||
+ registeredFeatures.put(name, consumer);
|
||||
+ }
|
||||
+
|
||||
+ public static class LeavesFeatureSet {
|
||||
+
|
||||
+ private static final Map<String, LeavesFeature> features = new HashMap<>();
|
||||
+
|
||||
+ public static void writeNBT(@NotNull CompoundTag tag) {
|
||||
+ CompoundTag featureNbt = new CompoundTag();
|
||||
+ features.values().forEach(feature -> feature.writeNBT(featureNbt));
|
||||
+ tag.put("Features", featureNbt);
|
||||
+ }
|
||||
+
|
||||
+ public static void register(LeavesFeature feature) {
|
||||
+ features.put(feature.name, feature);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record LeavesFeature(String name, String value) {
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Contract("_, _ -> new")
|
||||
+ public static LeavesFeature of(String name, boolean value) {
|
||||
+ return new LeavesFeature(name, Boolean.toString(value));
|
||||
+ }
|
||||
+
|
||||
+ public void writeNBT(@NotNull CompoundTag rules) {
|
||||
+ CompoundTag rule = new CompoundTag();
|
||||
+ rule.putString("Feature", name);
|
||||
+ rule.putString("Value", value);
|
||||
+ rules.put(name, rule);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record BladerenFeatureModifyPayload(String name, CompoundTag nbt) implements CustomPacketPayload {
|
||||
+
|
||||
+ public BladerenFeatureModifyPayload(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
+ this(buf.readUtf(), buf.readNbt());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(@NotNull FriendlyByteBuf buf) {
|
||||
+ buf.writeUtf(name);
|
||||
+ buf.writeNbt(nbt);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public ResourceLocation id() {
|
||||
+ return FEATURE_MODIFY_ID;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record BladerenHelloPayload(String version, CompoundTag nbt) implements CustomPacketPayload {
|
||||
+
|
||||
+ public BladerenHelloPayload(ResourceLocation location, @NotNull FriendlyByteBuf buf) {
|
||||
+ this(buf.readUtf(64), buf.readNbt());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(@NotNull FriendlyByteBuf buf) {
|
||||
+ buf.writeUtf(version);
|
||||
+ buf.writeNbt(nbt);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ @NotNull
|
||||
+ public ResourceLocation id() {
|
||||
+ return HELLO_ID;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
126
patches/server/0047-Leaves-Bladeren-mspt-sync-protocol.patch
Normal file
@@ -0,0 +1,126 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
|
||||
Date: Thu, 21 Dec 2023 20:06:50 +0800
|
||||
Subject: [PATCH] Leaves Bladeren mspt sync protocol
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index a0fd4fec133617893487586fd52e3a3a864871b4..d19f423debbeaedf955977c02aaf5f8e0016bea3 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -69,6 +69,9 @@ public class LuminolConfig {
|
||||
public static boolean pcaSyncProtocol = false;
|
||||
public static String pcaSyncPlayerEntity = "NOBODY";
|
||||
public static boolean bladerenLeavesProtocol = false;
|
||||
+ public static boolean msptSyncProtocol = false;
|
||||
+ public static int msptSyncTickInterval = 20;
|
||||
+
|
||||
|
||||
|
||||
public static void init() throws IOException {
|
||||
@@ -203,6 +206,8 @@ public class LuminolConfig {
|
||||
pcaSyncProtocol = get("gameplay.enable_pca_sync_protocol",pcaSyncProtocol);
|
||||
pcaSyncPlayerEntity = get("gameplay.pca_sync_player_entity",pcaSyncPlayerEntity,"Available values: NOBODY,EVERYBODY,OPS,OPS_AND_SELF");
|
||||
bladerenLeavesProtocol = get("gameplay.bladeren_leaves_protocol",bladerenLeavesProtocol);
|
||||
+ msptSyncProtocol = get("gameplay.bladeren_mspt_sync_protocol",bladerenLeavesProtocol);
|
||||
+ msptSyncTickInterval = get("gameplay.bladeren_mspt_sync_interval",msptSyncTickInterval);
|
||||
}
|
||||
|
||||
public static <T> T get(String key,T def){
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..de92ebdf9d51a4f9a58a7650b09f070e51710ef0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java
|
||||
@@ -0,0 +1,91 @@
|
||||
+package top.leavesmc.leaves.protocol.bladeren;
|
||||
+
|
||||
+import io.papermc.paper.threadedregions.ThreadedRegionizer;
|
||||
+import io.papermc.paper.threadedregions.TickData;
|
||||
+import io.papermc.paper.threadedregions.TickRegions;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectLists;
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import top.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
+import top.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
+
|
||||
+import java.util.List;
|
||||
+
|
||||
+@LeavesProtocol(namespace = "bladeren")
|
||||
+public class MsptSyncProtocol {
|
||||
+
|
||||
+ public static final String PROTOCOL_ID = "bladeren";
|
||||
+
|
||||
+ private static final ResourceLocation MSPT_SYNC = id("mspt_sync");
|
||||
+
|
||||
+ private static final List<ServerPlayer> players = ObjectLists.synchronize(new ObjectArrayList<>());
|
||||
+
|
||||
+ private static int tickCounter = 0;
|
||||
+
|
||||
+ @Contract("_ -> new")
|
||||
+ public static @NotNull ResourceLocation id(String path) {
|
||||
+ return new ResourceLocation(PROTOCOL_ID, path);
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.Init
|
||||
+ public static void init() {
|
||||
+ BladerenProtocol.registerFeature("mspt_sync", (player, compoundTag) -> {
|
||||
+ if (compoundTag.getString("Value").equals("true")) {
|
||||
+ onPlayerSubmit(player);
|
||||
+ } else {
|
||||
+ onPlayerLoggedOut(player);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.PlayerLeave
|
||||
+ public static void onPlayerLoggedOut(@NotNull ServerPlayer player) {
|
||||
+ if (LuminolConfig.msptSyncProtocol) {
|
||||
+ players.remove(player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ProtocolHandler.Ticker
|
||||
+ public static void tick() {
|
||||
+ if (LuminolConfig.msptSyncProtocol) {
|
||||
+ if (players.isEmpty()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (tickCounter++ % LuminolConfig.msptSyncTickInterval == 0) {
|
||||
+ for (ServerPlayer player : players){
|
||||
+ final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region = ((ServerLevel) player.level()).regioniser.getRegionAtUnsynchronised(player.sectionX,player.sectionZ);
|
||||
+
|
||||
+ if (region == null){
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final TickData.TickReportData reportData = region.getData().getRegionSchedulingHandle().getTickReport5s(System.nanoTime());
|
||||
+
|
||||
+ if (reportData != null){
|
||||
+ final TickData.SegmentData tpsData = reportData.tpsData().segmentAll();
|
||||
+ final double mspt = reportData.timePerTickData().segmentAll().average() / 1.0E6;
|
||||
+ final double tps = tpsData.average();
|
||||
+
|
||||
+ ProtocolUtils.sendPayloadPacket(player, MSPT_SYNC, buf -> {
|
||||
+ buf.writeDouble(mspt);
|
||||
+ buf.writeDouble(tps);
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void onPlayerSubmit(@NotNull ServerPlayer player) {
|
||||
+ if (LuminolConfig.msptSyncProtocol) {
|
||||
+ players.add(player);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
2044
patches/server/0048-Leaves-Syncmatica-Protocol.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Mon, 8 Jan 2024 12:19:29 +0000
|
||||
Subject: [PATCH] Do not process any packet if the leaves protocol supports are
|
||||
disabled
|
||||
|
||||
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
||||
index ebd28033ddf0fe6a354585dc2818a9b481d90ed4..33c7221a1f33cdb81dfac92fc3332f92cf3cd2d9 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package top.leavesmc.leaves.protocol;
|
||||
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java
|
||||
index de92ebdf9d51a4f9a58a7650b09f070e51710ef0..b309963dcf41f16a7b53e4cc2816975523ccba55 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java
|
||||
@@ -35,6 +35,9 @@ public class MsptSyncProtocol {
|
||||
|
||||
@ProtocolHandler.Init
|
||||
public static void init() {
|
||||
+ if (!LuminolConfig.msptSyncProtocol){
|
||||
+ return;
|
||||
+ }
|
||||
BladerenProtocol.registerFeature("mspt_sync", (player, compoundTag) -> {
|
||||
if (compoundTag.getString("Value").equals("true")) {
|
||||
onPlayerSubmit(player);
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java b/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
index fc229f23076147304754a267bcc345cc836b648b..6325f6441e28d915514e6b0ee9b450610e99b2c2 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
@@ -2,6 +2,7 @@ package top.leavesmc.leaves.protocol.syncmatica;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.netty.buffer.Unpooled;
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -68,6 +69,9 @@ public class CommunicationManager {
|
||||
|
||||
@ProtocolHandler.PlayerJoin
|
||||
public static void onPlayerJoin(ServerPlayer player) {
|
||||
+ if (!LuminolConfig.syncmaticaProtocol){
|
||||
+ return;
|
||||
+ }
|
||||
final ExchangeTarget newPlayer = player.connection.exchangeTarget;
|
||||
final VersionHandshakeServer hi = new VersionHandshakeServer(newPlayer);
|
||||
playerMap.put(newPlayer, player);
|
||||
@@ -78,6 +82,9 @@ public class CommunicationManager {
|
||||
|
||||
@ProtocolHandler.PlayerLeave
|
||||
public static void onPlayerLeave(ServerPlayer player) {
|
||||
+ if (!LuminolConfig.syncmaticaProtocol){
|
||||
+ return;
|
||||
+ }
|
||||
final ExchangeTarget oldPlayer = player.connection.exchangeTarget;
|
||||
final Collection<Exchange> potentialMessageTarget = oldPlayer.getExchanges();
|
||||
if (potentialMessageTarget != null) {
|
||||
@@ -92,6 +99,9 @@ public class CommunicationManager {
|
||||
|
||||
@ProtocolHandler.PayloadReceiver(payload = LeavesProtocolManager.LeavesPayload.class, ignoreId = true)
|
||||
public static void onPacketGet(ServerPlayer player, LeavesProtocolManager.LeavesPayload payload) {
|
||||
+ if (!LuminolConfig.syncmaticaProtocol){
|
||||
+ return;
|
||||
+ }
|
||||
onPacket(player.connection.exchangeTarget, payload.id(), payload.data());
|
||||
}
|
||||
|
||||
106
patches/server/0050-Leaves-Fix-Bladeren-Protocol.patch
Normal file
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Wed, 17 Jan 2024 14:10:33 +0000
|
||||
Subject: [PATCH] Leaves Fix Bladeren Protocol
|
||||
|
||||
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
||||
index 64a1d25973b032e8cab64bbffa6824a131676773..57a563b3f2d01719d490578907411d25ea07a658 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
||||
@@ -8,9 +8,7 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LeavesProtocol {
|
||||
-
|
||||
- String namespace() default "minecraft";
|
||||
-
|
||||
- String[] namespaces() default {};
|
||||
+
|
||||
+ String[] namespace();
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
||||
index 055f044ce6cef4377f6f577efdbfad0ec9a2d57b..18fc0e2c890020bf587f5b1d2e097126d3e19999 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
||||
@@ -56,7 +56,7 @@ public class LeavesProtocolManager {
|
||||
return;
|
||||
}
|
||||
|
||||
- Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = new HashMap<>();
|
||||
+ Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = KNOWN_TYPES.getOrDefault(protocol, new HashMap<>());
|
||||
for (final Method method : methods) {
|
||||
if (method.isBridge() || method.isSynthetic() || !Modifier.isStatic(method.getModifiers())) {
|
||||
continue;
|
||||
@@ -131,13 +131,13 @@ public class LeavesProtocolManager {
|
||||
|
||||
public static CustomPacketPayload getPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
||||
for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) {
|
||||
- if (!protocol.namespace().equals(id.getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), id.getNamespace())) {
|
||||
+ if (!ArrayUtils.contains(protocol.namespace(), id.getNamespace())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = KNOWN_TYPES.get(protocol);
|
||||
for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
||||
- if (receiver.ignoreId() || receiver.payloadId().equals(id.getPath()) || ArrayUtils.contains(receiver.payloadIds(), id.getPath())) {
|
||||
+ if (receiver.ignoreId() || ArrayUtils.contains(receiver.payloadId(), id.getPath())) {
|
||||
try {
|
||||
return map.get(receiver).newInstance(id, buf);
|
||||
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||
@@ -151,15 +151,14 @@ public class LeavesProtocolManager {
|
||||
|
||||
public static void handlePayload(ServerPlayer player, CustomPacketPayload payload) {
|
||||
for (LeavesProtocol protocol : KNOW_RECEIVERS.keySet()) {
|
||||
- if (!protocol.namespace().equals(payload.id().getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), payload.id().getNamespace())) {
|
||||
+ if (!ArrayUtils.contains(protocol.namespace(), payload.id().getNamespace())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<ProtocolHandler.PayloadReceiver, Method> map = KNOW_RECEIVERS.get(protocol);
|
||||
for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
||||
if (payload.getClass() == receiver.payload()) {
|
||||
- if (receiver.ignoreId() || receiver.payloadId().equals(payload.id().getPath()) ||
|
||||
- ArrayUtils.contains(receiver.payloadIds(), payload.id().getPath())) {
|
||||
+ if (receiver.ignoreId() || ArrayUtils.contains(receiver.payloadId(), payload.id().getPath())) {
|
||||
try {
|
||||
map.get(receiver).invoke(null, player, payload);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
@@ -222,7 +221,7 @@ public class LeavesProtocolManager {
|
||||
public static void handleMinecraftRegister(String channelId, ServerPlayer player) {
|
||||
for (LeavesProtocol protocol : MINECRAFT_REGISTER.keySet()) {
|
||||
String[] channel = channelId.split(":");
|
||||
- if (!protocol.namespace().equals(channel[0]) && !ArrayUtils.contains(protocol.namespaces(), channel[0])) {
|
||||
+ if (!ArrayUtils.contains(protocol.namespace(), channel[0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
||||
index d696f001d2576d1b61cc732c81f22eb52205072b..92ad6e9b1c0d9640b80c1ebe739c613d989eec21 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
||||
@@ -21,9 +21,7 @@ public class ProtocolHandler {
|
||||
|
||||
Class<? extends CustomPacketPayload> payload();
|
||||
|
||||
- String[] payloadIds() default {};
|
||||
-
|
||||
- String payloadId() default "";
|
||||
+ String[] payloadId();
|
||||
|
||||
boolean ignoreId() default false;
|
||||
}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java b/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
index 6325f6441e28d915514e6b0ee9b450610e99b2c2..19277aa7b9bd16b3e70d581d38a4c28e60165f65 100644
|
||||
--- a/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
+++ b/src/main/java/top/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java
|
||||
@@ -97,7 +97,7 @@ public class CommunicationManager {
|
||||
playerMap.remove(oldPlayer);
|
||||
}
|
||||
|
||||
- @ProtocolHandler.PayloadReceiver(payload = LeavesProtocolManager.LeavesPayload.class, ignoreId = true)
|
||||
+ @ProtocolHandler.PayloadReceiver(payload = LeavesProtocolManager.LeavesPayload.class, ignoreId = true, payloadId = "")
|
||||
public static void onPacketGet(ServerPlayer player, LeavesProtocolManager.LeavesPayload payload) {
|
||||
if (!LuminolConfig.syncmaticaProtocol){
|
||||
return;
|
||||
85
patches/server/0051-Fix-folia-181-on-1.20.2.patch
Normal file
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 21 Jan 2024 00:27:17 +0000
|
||||
Subject: [PATCH] Fix folia #181 on 1.20.2
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 875afb57c7f0c4e3d0bc752d86a8308147eee31a..e91061b96701bc46f5a6ed8315eb6c8da8a74f3a 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -36,6 +36,7 @@ public class LuminolConfig {
|
||||
public static boolean disableOfflineModeWarning = false;
|
||||
public static boolean fixSpectorTeleportFolia = false;
|
||||
public static boolean disableRootUserWarning = false;
|
||||
+ public static boolean fixDoubleEntitySchedulerRetring = false;
|
||||
|
||||
public static boolean safeTeleportation = true;
|
||||
public static boolean enableSandDuping = false;
|
||||
@@ -153,6 +154,7 @@ public class LuminolConfig {
|
||||
fixSpectorTeleportFolia = get("misc.fix_folia_spector_teleport",fixSpectorTeleportFolia);
|
||||
disableOfflineModeWarning = get("misc.disable_offline_mode_warning",disableOfflineModeWarning);
|
||||
disableRootUserWarning = get("misc.disable_root_user_warning",disableRootUserWarning);
|
||||
+ fixDoubleEntitySchedulerRetring = get("misc.fix_folia_double_entity_scheduler_retring",fixDoubleEntitySchedulerRetring,"Fix https://github.com/PaperMC/Folia/pull/181 on Folia");
|
||||
|
||||
if (tpsbarEnabled){
|
||||
initTpsbar();
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index e1ace2ad411b8d54c56660b41e774a1c998b3ac3..5303d92484b4afdc697c79eecb71d5f24d670aa4 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -4,6 +4,8 @@ import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
+
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.CrashReportCategory;
|
||||
@@ -69,6 +71,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
protected final ServerPlayer player;
|
||||
protected final org.bukkit.craftbukkit.CraftServer cserver;
|
||||
public boolean processedDisconnect;
|
||||
+ //Luminol start - Fix folia #181
|
||||
+ private boolean handledDisconnect = false;
|
||||
+ //Luminol end
|
||||
|
||||
public CraftPlayer getCraftPlayer() {
|
||||
return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity();
|
||||
@@ -86,6 +91,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
ServerCommonPacketListenerImpl.LOGGER.info("Stopping singleplayer server as player logged out");
|
||||
this.server.halt(false);
|
||||
}
|
||||
+ //Luminol start - Fix folia #181
|
||||
+ if (this.handledDisconnect && LuminolConfig.fixDoubleEntitySchedulerRetring){
|
||||
+ return;
|
||||
+ }
|
||||
+ this.handledDisconnect = true;
|
||||
+ //Luminol end
|
||||
+
|
||||
this.player.getBukkitEntity().taskScheduler.retire(); // Folia - region threading
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 59cd97446b9dace1a887e35761bc94c88348256a..c4652f250e22f33e8505183b4050e08aedf9245c 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -29,6 +29,8 @@ import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
+
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.Util;
|
||||
@@ -337,7 +339,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
public void tick() {
|
||||
// Folia start - region threading
|
||||
this.keepConnectionAlive();
|
||||
- if (this.player.wonGame) {
|
||||
+ if ((LuminolConfig.fixDoubleEntitySchedulerRetring && this.processedDisconnect) || this.player.wonGame) { //Luminol - Fix folia #181
|
||||
return;
|
||||
}
|
||||
// Folia end - region threading
|
||||
45
patches/server/0052-Piston-fixes-from-molean-server.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 21 Jan 2024 11:49:38 +0000
|
||||
Subject: [PATCH] Piston fixes from molean server
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 3a5c8f1f9a8173777b00d43c15e8e313526d3e28..9bd6d4881280196a437161a9375ac8ee5e0f9231 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1428,7 +1428,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
if (movement.lengthSqr() <= 1.0E-7D) {
|
||||
return movement;
|
||||
} else {
|
||||
- long i = this.level().getGameTime();
|
||||
+ long i = this.level().getRedstoneGameTime(); //Luminol - Piston fixes from molean server
|
||||
|
||||
if (i != this.pistonDeltasGameTime) {
|
||||
Arrays.fill(this.pistonDeltas, 0.0D);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
index cdcf11fb9e4690d74b30fe0ade842d6574464624..141b806493f25854fc49f90816cd22e7d5d74e6f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
@@ -139,7 +139,7 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
if (tileentity instanceof PistonMovingBlockEntity) {
|
||||
PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity;
|
||||
|
||||
- if (tileentitypiston.isExtending() && (tileentitypiston.getProgress(0.0F) < 0.5F || world.getGameTime() == tileentitypiston.getLastTicked() || ((ServerLevel) world).isHandlingTick())) {
|
||||
+ if (tileentitypiston.isExtending() && (tileentitypiston.getProgress(0.0F) < 0.5F || world.getRedstoneGameTime() == tileentitypiston.getLastTicked() || ((ServerLevel) world).isHandlingTick())) { //Luminol - Piston fixes from molean server
|
||||
b0 = 2;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
index a595abb43853cd4c3f5886a83527c6cbe4a3e8f7..2284dfcb09d9a7c6f670e5266a3f2856c2d40e8d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
@@ -277,7 +277,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
}
|
||||
|
||||
public static void tick(Level world, BlockPos pos, BlockState state, PistonMovingBlockEntity blockEntity) {
|
||||
- blockEntity.lastTicked = world.getGameTime();
|
||||
+ blockEntity.lastTicked = world.getRedstoneGameTime(); //Luminol - Piston fixes from molean server
|
||||
blockEntity.progressO = blockEntity.progress;
|
||||
if (blockEntity.progressO >= 1.0F) {
|
||||
if (world.isClientSide && blockEntity.deathTicks < 5) {
|
||||
@@ -0,0 +1,80 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Fri, 26 Jan 2024 10:58:48 +0000
|
||||
Subject: [PATCH] Teleport async if the entity was moving to another region
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index e91061b96701bc46f5a6ed8315eb6c8da8a74f3a..55d0ae641f1de570a293d1d6fe03da3ab2bba1c4 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -43,6 +43,8 @@ public class LuminolConfig {
|
||||
public static boolean enableVoidTrading = false;
|
||||
public static boolean allowIncorrectTripwireUpdating = false;
|
||||
public static boolean useVanillaRandomSource = false;
|
||||
+ public static boolean fixLargePosMoving = false;
|
||||
+ public static boolean warnOnLargeMovingDetected = true;
|
||||
|
||||
public static RegionFileFormat regionFormatName = RegionFileFormat.ANVIL;
|
||||
public static int regionFormatLinearCompressionLevel = 1;
|
||||
@@ -165,6 +167,8 @@ public class LuminolConfig {
|
||||
enableVoidTrading = get("fixes.enable_void_trading",enableVoidTrading);
|
||||
allowIncorrectTripwireUpdating = get("fixes.allow_incorrect_trip_wire_updaing",allowIncorrectTripwireUpdating);
|
||||
useVanillaRandomSource = get("fixes.use_vanilla_random_source",useVanillaRandomSource,"RNG feature related");
|
||||
+ fixLargePosMoving = get("fixes.fix_large_pos_moving", fixLargePosMoving,"Fix an entity moving issue on folia which is not fixed yet");
|
||||
+ warnOnLargeMovingDetected = get("fixes.warn_on_large_pos_moving",warnOnLargeMovingDetected);
|
||||
|
||||
regionFormatName = RegionFileFormat.fromString(get("save.region-format.format", regionFormatName.name()));
|
||||
if (regionFormatName.equals(RegionFileFormat.INVALID)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 9bd6d4881280196a437161a9375ac8ee5e0f9231..18fdb265714584d4ee759d86cc8a10b13742e153 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -7,6 +7,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import com.mojang.logging.LogUtils;
|
||||
+import io.papermc.paper.util.TickThread;
|
||||
import it.unimi.dsi.fastutil.objects.Object2DoubleArrayMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
|
||||
import java.util.Arrays;
|
||||
@@ -1084,9 +1085,39 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
// Paper end - detailed watchdog information
|
||||
|
||||
+ //Luminol start - Fix large pos moving
|
||||
+ private volatile boolean preventMoving = false;
|
||||
+ //Luminol end
|
||||
+
|
||||
public void move(MoverType movementType, Vec3 movement) {
|
||||
// Paper start - detailed watchdog information
|
||||
io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main");
|
||||
+ //Luminol start - Fix high position moving
|
||||
+ if (LuminolConfig.fixLargePosMoving && TickThread.isTickThread()){ //Except the threads because it may be called by the chunk system worker thread
|
||||
+ if (this.preventMoving){
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ var finalPosition = movement.add(this.position);
|
||||
+ if (!TickThread.isTickThreadFor(((ServerLevel) this.level),finalPosition)){
|
||||
+ this.preventMoving = true;
|
||||
+ this.teleportAsync(
|
||||
+ (ServerLevel) this.level(),
|
||||
+ finalPosition,
|
||||
+ this.getYRot(), this.getXRot(),
|
||||
+ null, PlayerTeleportEvent.TeleportCause.UNKNOWN,
|
||||
+ Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS,
|
||||
+ result -> {
|
||||
+ this.preventMoving = false;
|
||||
+ }
|
||||
+ );
|
||||
+ if (LuminolConfig.warnOnLargeMovingDetected){
|
||||
+ MinecraftServer.LOGGER.warn("Entity {} with entityId {} has tried moving to another region!",this.type.getCategory().getName(),this.getId());
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
synchronized (this.posLock) {
|
||||
this.moveStartX = this.getX();
|
||||
this.moveStartY = this.getY();
|
||||
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 09:51:56 +0000
|
||||
Subject: [PATCH] Sparkly Paper Optimize canSee checks
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 4709782f3e858edfa6ce25696462eb45909885ee..3cba356b74362c2fc010d0c1bfb6eeecb449908e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1419,7 +1419,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Folia end - region threading
|
||||
|
||||
// CraftBukkit start - respect vanish API
|
||||
- if (flag && (!io.papermc.paper.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSee(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading
|
||||
+ if (flag && (!io.papermc.paper.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSeeChunkMapUpdatePlayer(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading // SparklyPaper - optimize canSee checks
|
||||
flag = false;
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 06c92a2d3ecb3b747c2303819f72c1c41967af8c..7ae6925732c347ec97c94c5fdfd0012fbe6820fc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -183,7 +183,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
private boolean hasPlayedBefore = false;
|
||||
private final ConversationTracker conversationTracker = new ConversationTracker();
|
||||
private final Set<String> channels = new HashSet<String>();
|
||||
- private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
|
||||
+ private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // SparklyPaper - optimize canSee checks
|
||||
private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper
|
||||
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
|
||||
private int hash = 0;
|
||||
@@ -2075,9 +2075,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public boolean canSee(org.bukkit.entity.Entity entity) {
|
||||
- return this.equals(entity) || entity.isVisibleByDefault() ^ this.invertedVisibilityEntities.containsKey(entity.getUniqueId()); // SPIGOT-7312: Can always see self
|
||||
+ return this.equals(entity) || entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks
|
||||
}
|
||||
|
||||
+ // SparklyPaper - optimize canSee checks
|
||||
+ // The check in ChunkMap#updatePlayer already rejects if it is the same entity, so we don't need to check it twice, especially because CraftPlayer's equals check is a bit expensive
|
||||
+ public boolean canSeeChunkMapUpdatePlayer(org.bukkit.entity.Entity entity) {
|
||||
+ return entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks
|
||||
+ }
|
||||
+ // SparklyPaper end
|
||||
+
|
||||
public boolean canSee(UUID uuid) {
|
||||
org.bukkit.entity.Entity entity = this.getServer().getPlayer(uuid);
|
||||
if (entity == null) {
|
||||
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 09:52:09 +0000
|
||||
Subject: [PATCH] Gale Skip entity move if movement is zero
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 18fdb265714584d4ee759d86cc8a10b13742e153..ec255db477e6308cc0fbe336b7bebeac75b97b2a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -317,6 +317,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
public float yRotO;
|
||||
public float xRotO;
|
||||
private AABB bb;
|
||||
+ private boolean boundingBoxChanged = false; // Gale - VMP - skip entity move if movement is zero
|
||||
public boolean onGround;
|
||||
public boolean horizontalCollision;
|
||||
public boolean verticalCollision;
|
||||
@@ -1090,6 +1091,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
//Luminol end
|
||||
|
||||
public void move(MoverType movementType, Vec3 movement) {
|
||||
+ // Gale start - VMP - skip entity move if movement is zero
|
||||
+ if (!this.boundingBoxChanged && movement.equals(Vec3.ZERO)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Gale end - VMP - skip entity move if movement is zero
|
||||
// Paper start - detailed watchdog information
|
||||
io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main");
|
||||
//Luminol start - Fix high position moving
|
||||
@@ -4875,6 +4881,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
public final void setBoundingBox(AABB boundingBox) {
|
||||
+ // Gale start - VMP - skip entity move if movement is zero
|
||||
+ if (!this.bb.equals(boundingBox)) {
|
||||
+ this.boundingBoxChanged = true;
|
||||
+ }
|
||||
+ // Gale end - VMP - skip entity move if movement is zero
|
||||
// CraftBukkit start - block invalid bounding boxes
|
||||
double minX = boundingBox.minX,
|
||||
minY = boundingBox.minY,
|
||||
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 09:52:24 +0000
|
||||
Subject: [PATCH] Gale Check frozen ticks before landing block
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index ecbacbed29af51d949122b21c3ae9fc95885c6d8..3c83ff19c40eb44eae3ed9f7db4f5291d080b32c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -591,11 +591,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
protected void tryAddFrost() {
|
||||
- if (!this.getBlockStateOnLegacy().isAir()) {
|
||||
int i = this.getTicksFrozen();
|
||||
|
||||
if (i > 0) {
|
||||
- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED);
|
||||
+ AttributeInstance attributemodifiable = this.getBlockStateOnLegacy().isAir() ? null : this.getAttribute(Attributes.MOVEMENT_SPEED); // Gale - Lithium - check frozen ticks before landing block
|
||||
|
||||
if (attributemodifiable == null) {
|
||||
return;
|
||||
@@ -605,7 +604,6 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION));
|
||||
}
|
||||
- }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 09:52:48 +0000
|
||||
Subject: [PATCH] Gale Don't trigger lootable refresh for non-player
|
||||
interaction
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
index 02364a148b347e3669275553004391e31d77c0b5..6c6ed0e9877c7e0c9804f3c2c786a61c301e318f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -70,6 +70,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
}
|
||||
|
||||
public void unpackLootTable(@Nullable Player player) {
|
||||
+ if (player == null) return; // Gale - EMC - don't trigger lootable refresh for non-player interaction
|
||||
if (this.level != null && this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper - don't unpack loot table if not in world
|
||||
LootTable lootTable = this.level.getServer().getLootData().getLootTable(this.lootTable);
|
||||
if (player instanceof ServerPlayer) {
|
||||
187
patches/server/0058-Gale-Use-platform-math-functions.patch
Normal file
@@ -0,0 +1,187 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 09:31:27 +0000
|
||||
Subject: [PATCH] Gale Use platform math functions
|
||||
|
||||
License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://galemc.org
|
||||
|
||||
This patch is based on the following patch:
|
||||
"Use Math.floor instead of fastfloor"
|
||||
By: Xymb <xymb@endcrystal.me>
|
||||
As part of: Kaiiju (https://github.com/KaiijuMC/Kaiiju)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
* Comparison of floor methods used in Paper *
|
||||
|
||||
Measure shown is floored number of milliseconds
|
||||
(nanoseconds integer-divided by 1_000_000
|
||||
taken to get the floor of 1000 randomly chosen doubles
|
||||
(all in the range of [-Integer.MAX_VALUE + 10, Integer.MAX_VALUE - 10])
|
||||
100_000 times (making it 100_000_000 floor operations total)
|
||||
and adding it to a total.
|
||||
|
||||
We are testing the following methods:
|
||||
* net.minecraft.util.Mth.floor
|
||||
* java.lang.Math.floor
|
||||
* java.lang.StrictMath.floor
|
||||
* org.apache.commons.math3.util.FastMath.floor
|
||||
* org.apache.commons.math3.util.FastMath.floor, but with a hot start (see comment in code)
|
||||
* io.papermc.paper.util.MCUtil.fastFloor
|
||||
|
||||
The tests performed clearly show that Math.floor is the fastest.
|
||||
This is most likely due to java.lang.Math's usage of the @IntrinsicCandidate
|
||||
annotation, which allows the JVM to use a more optimized implementation at runtime.
|
||||
However, in the case that there is no intrinsic replacement for Math.floor,
|
||||
it defers to StrictMath.floor, which relies on a number of native methods, and is
|
||||
still much faster than the existing Minecraft utility functions.
|
||||
Therefore, using Math.floor instead of these functions is better regardless.
|
||||
In Apache Commons Math 4, FastMath.floor has also been removed in favor of Math.floor.
|
||||
|
||||
The versions used:
|
||||
* Windows 10 Home 21H2 19044.3086
|
||||
* OpenJDK Runtime Environment Temurin-19.0.2+7 (build 19.0.2+7)
|
||||
* Paper a3c760e6af1e8c7244ef75c6da6e6df278a79e14 on Minecraft 1.20.1
|
||||
* Apache Commons Math 3.6.1
|
||||
|
||||
Results:
|
||||
Total is of type int Total is of type double
|
||||
----------------------------------------------------------------------------------
|
||||
Mth.floor 2113 (double) Mth.floor 2658
|
||||
(int) Math.floor 130 Math.floor 194
|
||||
(int) StrictMath.floor 835 StrictMath.floor 381
|
||||
(int) FastMath.floor 412 FastMath.floor 376
|
||||
(int) FastMath.floor with hot start 359 FastMath.floor with hot start 321
|
||||
MCUtil.fastFloor 2284 (double) MCUtil.fastFloor 2469
|
||||
|
||||
Code is below:
|
||||
```java
|
||||
package somepackage;
|
||||
|
||||
import io.papermc.paper.util.MCUtil;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// IF FastMath.floor with a hot start:
|
||||
// FastMath.floor(37485.5);
|
||||
|
||||
var random = new Random(4889338);
|
||||
int size = 1000;
|
||||
var values = new double[size];
|
||||
double bound = Integer.MAX_VALUE - 10;
|
||||
for (int i = 0; i < size; i++) {
|
||||
values[i] = random.nextDouble(bound * 2) - bound;
|
||||
}
|
||||
int repeats = 100_000;
|
||||
|
||||
// int total = 0;
|
||||
// OR
|
||||
// double total = 0;
|
||||
|
||||
long start = System.nanoTime();
|
||||
for (int repeat = 0; repeat < repeats; repeat++) {
|
||||
for (int index = 0; index < size; index++) {
|
||||
total += insert_function_being_tested_here(values[index]);
|
||||
}
|
||||
}
|
||||
long diff = System.nanoTime() - start;
|
||||
System.out.println(total);
|
||||
System.out.println(diff / 1_000_000L);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
index a149d98be7b4744f18d4ed4940881e13a76e4a7c..ad61afcfe1d0b01b17bc02977e8ff2b8d0420088 100644
|
||||
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
|
||||
@@ -166,13 +166,11 @@ public final class MCUtil {
|
||||
}
|
||||
|
||||
public static int fastFloor(double x) {
|
||||
- int truncated = (int)x;
|
||||
- return x < (double)truncated ? truncated - 1 : truncated;
|
||||
+ return (int) Math.floor(x); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int fastFloor(float x) {
|
||||
- int truncated = (int)x;
|
||||
- return x < (double)truncated ? truncated - 1 : truncated;
|
||||
+ return (int) Math.floor(x); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static float normalizeYaw(float f) {
|
||||
@@ -233,11 +231,11 @@ public final class MCUtil {
|
||||
}
|
||||
|
||||
public static int getChunkCoordinate(final double coordinate) {
|
||||
- return MCUtil.fastFloor(coordinate) >> 4;
|
||||
+ return ((int) Math.floor(coordinate)) >> 4; // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int getBlockCoordinate(final double coordinate) {
|
||||
- return MCUtil.fastFloor(coordinate);
|
||||
+ return (int) Math.floor(coordinate); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static long getBlockKey(final int x, final int y, final int z) {
|
||||
diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java
|
||||
index 33ace08d15bbcad66c09c7bd65dd03e784246e8f..d04586223a9b2a30efb17da01fb7f3e8f2a6af7b 100644
|
||||
--- a/src/main/java/net/minecraft/util/Mth.java
|
||||
+++ b/src/main/java/net/minecraft/util/Mth.java
|
||||
@@ -51,13 +51,11 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static int floor(float value) {
|
||||
- int i = (int)value;
|
||||
- return value < (float)i ? i - 1 : i;
|
||||
+ return (int) Math.floor(value); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int floor(double value) {
|
||||
- int i = (int)value;
|
||||
- return value < (double)i ? i - 1 : i;
|
||||
+ return (int) Math.floor(value); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static long lfloor(double value) {
|
||||
@@ -74,13 +72,11 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static int ceil(float value) {
|
||||
- int i = (int)value;
|
||||
- return value > (float)i ? i + 1 : i;
|
||||
+ return (int) Math.ceil(value); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int ceil(double value) {
|
||||
- int i = (int)value;
|
||||
- return value > (double)i ? i + 1 : i;
|
||||
+ return (int) Math.ceil(value); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int clamp(int value, int min, int max) {
|
||||
@@ -116,15 +112,7 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static double absMax(double a, double b) {
|
||||
- if (a < 0.0D) {
|
||||
- a = -a;
|
||||
- }
|
||||
-
|
||||
- if (b < 0.0D) {
|
||||
- b = -b;
|
||||
- }
|
||||
-
|
||||
- return Math.max(a, b);
|
||||
+ return Math.max(Math.abs(a), Math.abs(b)); // Gale - use platform math functions
|
||||
}
|
||||
|
||||
public static int floorDiv(int dividend, int divisor) {
|
||||
@@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Sun, 28 Jan 2024 10:48:45 +0000
|
||||
Subject: [PATCH] Added config for secondary POI optimizations
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 55d0ae641f1de570a293d1d6fe03da3ab2bba1c4..e531453e3d25700e38ff41548c7e32e278a6304d 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -68,6 +68,7 @@ public class LuminolConfig {
|
||||
public static int asyncPathProcessingKeepalive = 60;
|
||||
public static boolean enableAsyncMobSpawning = false;
|
||||
public static boolean useAlternateKeepAlive = false;
|
||||
+ public static boolean skipSecondaryPOIIfIsEmpty = true;
|
||||
|
||||
public static boolean pcaSyncProtocol = false;
|
||||
public static String pcaSyncPlayerEntity = "NOBODY";
|
||||
@@ -211,6 +212,7 @@ public class LuminolConfig {
|
||||
enableAsyncMobSpawning = get("optimizations.enable_async_mob_spawning",enableAsyncMobSpawning);
|
||||
RegionizedWorldData.initMobSpawningExecutor();
|
||||
useAlternateKeepAlive = get("optimizations.enable_alternative_keep_alive_handling",useAlternateKeepAlive,"Enabling this sends a keepalive packet once per second to a player, and only kicks for timeout if none of them were responded to in 30 seconds. Responding to any of them in any order will keep the player connected. AKA, it won't kick your players because one packet gets dropped somewhere along the lines(From purpur)");
|
||||
+ skipSecondaryPOIIfIsEmpty = get("optimizations.skip_secondary_poi_if_is_empty",skipSecondaryPOIIfIsEmpty);
|
||||
|
||||
pcaSyncProtocol = get("gameplay.enable_pca_sync_protocol",pcaSyncProtocol);
|
||||
pcaSyncPlayerEntity = get("gameplay.pca_sync_player_entity",pcaSyncPlayerEntity,"Available values: NOBODY,EVERYBODY,OPS,OPS_AND_SELF");
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
index 75dc06a3041bfdfb08c914eb50cfa282ae9eb2fe..6a95fe3f648a54b3cbb2b38a294028043c8012c9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
@@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
+
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.GlobalPos;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
@@ -23,10 +25,12 @@ public class SecondaryPoiSensor extends Sensor<Villager> {
|
||||
@Override
|
||||
protected void doTick(ServerLevel world, Villager entity) {
|
||||
// Gale start - Lithium - skip secondary POI sensor if absent
|
||||
- var secondaryPoi = entity.getVillagerData().getProfession().secondaryPoi();
|
||||
- if (secondaryPoi.isEmpty()) {
|
||||
- entity.getBrain().eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE);
|
||||
- return;
|
||||
+ if (LuminolConfig.skipSecondaryPOIIfIsEmpty){
|
||||
+ var secondaryPoi = entity.getVillagerData().getProfession().secondaryPoi();
|
||||
+ if (secondaryPoi.isEmpty()) {
|
||||
+ entity.getBrain().eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
// Gale end - Lithium - skip secondary POI sensor if absent
|
||||
ResourceKey<Level> resourceKey = world.dimension();
|
||||
166
patches/server/0060-Leaves-Command-Utilities.patch
Normal file
@@ -0,0 +1,166 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Mon, 29 Jan 2024 12:47:41 +0000
|
||||
Subject: [PATCH] Leaves Command Utilities
|
||||
|
||||
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/command/CommandArgument.java b/src/main/java/top/leavesmc/leaves/command/CommandArgument.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..eadc6d168fb13299348b0c275ae352ee2f1e1ea2
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/command/CommandArgument.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package top.leavesmc.leaves.command;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.List;
|
||||
+
|
||||
+public class CommandArgument {
|
||||
+
|
||||
+ private final List<CommandArgumentType<?>> argumentTypes;
|
||||
+ private final List<List<String>> tabComplete;
|
||||
+
|
||||
+ public CommandArgument(CommandArgumentType<?>... argumentTypes) {
|
||||
+ this.argumentTypes = List.of(argumentTypes);
|
||||
+ this.tabComplete = new ArrayList<>();
|
||||
+ for (int i = 0; i < argumentTypes.length; i++) {
|
||||
+ tabComplete.add(new ArrayList<>());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public List<String> tabComplete(int n) {
|
||||
+ if (tabComplete.size() > n) {
|
||||
+ return tabComplete.get(n);
|
||||
+ } else {
|
||||
+ return List.of();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public CommandArgument setTabComplete(int index, List<String> list) {
|
||||
+ tabComplete.set(index, list);
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ public CommandArgumentResult parse(int index, String @NotNull [] args) {
|
||||
+ Object[] result = new Object[argumentTypes.size()];
|
||||
+ Arrays.fill(result, null);
|
||||
+ for (int i = index, j = 0; i < args.length && j < result.length; i++, j++) {
|
||||
+ result[j] = argumentTypes.get(j).pasre(args[i]);
|
||||
+ }
|
||||
+ return new CommandArgumentResult(new ArrayList<>(Arrays.asList(result)));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/command/CommandArgumentResult.java b/src/main/java/top/leavesmc/leaves/command/CommandArgumentResult.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..340eaca64c96180b895a075ce9e44402cd104eed
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/command/CommandArgumentResult.java
|
||||
@@ -0,0 +1,62 @@
|
||||
+package top.leavesmc.leaves.command;
|
||||
+
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import org.bukkit.util.Vector;
|
||||
+
|
||||
+import java.util.List;
|
||||
+import java.util.Objects;
|
||||
+
|
||||
+public class CommandArgumentResult {
|
||||
+
|
||||
+ private final List<Object> result;
|
||||
+
|
||||
+ public CommandArgumentResult(List<Object> result) {
|
||||
+ this.result = result;
|
||||
+ }
|
||||
+
|
||||
+ public Integer readInt(int def) {
|
||||
+ return Objects.requireNonNullElse(read(Integer.class), def);
|
||||
+ }
|
||||
+
|
||||
+ public Double readDouble(double def) {
|
||||
+ return Objects.requireNonNullElse(read(Double.class), def);
|
||||
+ }
|
||||
+
|
||||
+ public String readString(String def) {
|
||||
+ return Objects.requireNonNullElse(read(String.class), def);
|
||||
+ }
|
||||
+
|
||||
+ public BlockPos readPos() {
|
||||
+ Integer[] pos = {read(Integer.class), read(Integer.class), read(Integer.class)};
|
||||
+ for (Integer po : pos) {
|
||||
+ if (po == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ return new BlockPos(pos[0], pos[1], pos[2]);
|
||||
+ }
|
||||
+
|
||||
+ public Vector readVector() {
|
||||
+ Double[] pos = {read(Double.class), read(Double.class), read(Double.class)};
|
||||
+ for (Double po : pos) {
|
||||
+ if (po == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ return new Vector(pos[0], pos[1], pos[2]);
|
||||
+ }
|
||||
+
|
||||
+ public <T> T read(Class<T> tClass) {
|
||||
+ if (result.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ Object obj = result.remove(0);
|
||||
+ if (tClass.isInstance(obj)) {
|
||||
+ return tClass.cast(obj);
|
||||
+ } else {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/command/CommandArgumentType.java b/src/main/java/top/leavesmc/leaves/command/CommandArgumentType.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..edf12195c7224ca2fb5d3c2ac3fcf485d3049d07
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/command/CommandArgumentType.java
|
||||
@@ -0,0 +1,37 @@
|
||||
+package top.leavesmc.leaves.command;
|
||||
+
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+public abstract class CommandArgumentType<E> {
|
||||
+
|
||||
+ public static final CommandArgumentType<Integer> INTEGER = new CommandArgumentType<>() {
|
||||
+ @Override
|
||||
+ public Integer pasre(@NotNull String arg) {
|
||||
+ try {
|
||||
+ return Integer.parseInt(arg);
|
||||
+ } catch (NumberFormatException e) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ public static final CommandArgumentType<Double> DOUBLE = new CommandArgumentType<>() {
|
||||
+ @Override
|
||||
+ public Double pasre(@NotNull String arg) {
|
||||
+ try {
|
||||
+ return Double.parseDouble(arg);
|
||||
+ } catch (NumberFormatException e) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ public static final CommandArgumentType<String> STRING = new CommandArgumentType<>() {
|
||||
+ @Override
|
||||
+ public String pasre(@NotNull String arg) {
|
||||
+ return arg;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ public abstract E pasre(@NotNull String arg);
|
||||
+}
|
||||
3259
patches/server/0061-Leaves-fakeplayer-support.patch
Normal file
102
patches/server/0062-Io_uring-channel-type-support.patch
Normal file
@@ -0,0 +1,102 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Tue, 30 Jan 2024 13:08:25 +0000
|
||||
Subject: [PATCH] Io_uring channel type support
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 8a926993088d33983f75071b3320dd67c3e857c3..aa1033e0de7d59c32acd2afa58c0b916588b97ed 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -39,6 +39,7 @@ dependencies {
|
||||
log4jPlugins.annotationProcessorConfigurationName("org.apache.logging.log4j:log4j-core:2.19.0") // Paper - Needed to generate meta for our Log4j plugins
|
||||
runtimeOnly(log4jPlugins.output)
|
||||
alsoShade(log4jPlugins.output)
|
||||
+ implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.21.Final:linux-x86_64") //Luminol - io_uring Libraries
|
||||
implementation("io.netty:netty-codec-haproxy:4.1.97.Final") // Paper - Add support for proxy protocol
|
||||
// Paper end
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 610642b0a0c3f17c66ec27ed812b97c68cee1be6..87f5c0fc3f92feecb167c3e28d86a67ba848cb61 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -37,6 +37,7 @@ public class LuminolConfig {
|
||||
public static boolean fixSpectorTeleportFolia = false;
|
||||
public static boolean disableRootUserWarning = false;
|
||||
public static boolean fixDoubleEntitySchedulerRetring = false;
|
||||
+ public static boolean enableIoUring = false;
|
||||
|
||||
public static boolean safeTeleportation = true;
|
||||
public static boolean enableSandDuping = false;
|
||||
@@ -185,6 +186,7 @@ public class LuminolConfig {
|
||||
disableOfflineModeWarning = get("misc.disable_offline_mode_warning",disableOfflineModeWarning);
|
||||
disableRootUserWarning = get("misc.disable_root_user_warning",disableRootUserWarning);
|
||||
fixDoubleEntitySchedulerRetring = get("misc.fix_folia_double_entity_scheduler_retring",fixDoubleEntitySchedulerRetring,"Fix https://github.com/PaperMC/Folia/pull/181 on Folia");
|
||||
+ enableIoUring = get("misc.enable_io_uring_support",enableIoUring);
|
||||
|
||||
if (tpsbarEnabled){
|
||||
initTpsbar();
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index 81090d1b5d67506268a41c6387a1d45302e88a5c..637d321b75dc7b5653ff9aa6134f900c634a19d8 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -20,9 +20,11 @@ import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
-import io.netty.channel.socket.ServerSocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
+import io.netty.incubator.channel.uring.IOUring;
|
||||
+import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
|
||||
+import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
|
||||
import io.netty.util.HashedWheelTimer;
|
||||
import io.netty.util.Timeout;
|
||||
import io.netty.util.Timer;
|
||||
@@ -35,6 +37,8 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
+
|
||||
+import me.earthme.luminol.LuminolConfig;
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.network.BandwidthDebugMonitor;
|
||||
@@ -73,6 +77,10 @@ public class ServerConnectionListener {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ //Luminol start - io_uring support
|
||||
+ public static final Supplier<IOUringEventLoopGroup> SERVER_IO_URING_WORKER_GROUP = Suppliers.memoize(() -> new IOUringEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty IO_URING Server IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(LOGGER)).build()));
|
||||
+ //Luminol end
|
||||
+
|
||||
public ServerConnectionListener(MinecraftServer server) {
|
||||
this.server = server;
|
||||
this.running = true;
|
||||
@@ -89,8 +97,14 @@ public class ServerConnectionListener {
|
||||
synchronized (this.channels) {
|
||||
Class oclass;
|
||||
EventLoopGroup eventloopgroup;
|
||||
-
|
||||
- if (Epoll.isAvailable() && this.server.isEpollEnabled()) {
|
||||
+ //Luminol start - io_uring support
|
||||
+ if (IOUring.isAvailable() && LuminolConfig.enableIoUring){
|
||||
+ eventloopgroup = SERVER_IO_URING_WORKER_GROUP.get();
|
||||
+ oclass = IOUringServerSocketChannel.class;
|
||||
+ ServerConnectionListener.LOGGER.info("Using io_uring channel type");
|
||||
+ }
|
||||
+ else if (Epoll.isAvailable() && this.server.isEpollEnabled()) {
|
||||
+ //Luminol end
|
||||
// Paper start
|
||||
if (address instanceof io.netty.channel.unix.DomainSocketAddress) {
|
||||
oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class;
|
||||
@@ -100,7 +114,8 @@ public class ServerConnectionListener {
|
||||
// Paper end
|
||||
eventloopgroup = (EventLoopGroup) ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP.get();
|
||||
ServerConnectionListener.LOGGER.info("Using epoll channel type");
|
||||
- } else {
|
||||
+ }
|
||||
+ else {
|
||||
oclass = NioServerSocketChannel.class;
|
||||
eventloopgroup = (EventLoopGroup) ServerConnectionListener.SERVER_EVENT_GROUP.get();
|
||||
ServerConnectionListener.LOGGER.info("Using default channel type");
|
||||
@@ -0,0 +1,178 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <novau233@163.com>
|
||||
Date: Thu, 1 Feb 2024 09:51:45 +0000
|
||||
Subject: [PATCH] Prevent teleportAsync calling during moving event being
|
||||
handled
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
index 87f5c0fc3f92feecb167c3e28d86a67ba848cb61..0a1a8016f5e51163c2c375a9444d68d3d68544d1 100644
|
||||
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
|
||||
@@ -46,6 +46,8 @@ public class LuminolConfig {
|
||||
public static boolean useVanillaRandomSource = false;
|
||||
public static boolean fixLargePosMoving = false;
|
||||
public static boolean warnOnLargeMovingDetected = true;
|
||||
+ public static boolean preventTeleportAsyncDuringMovingEvent = false;
|
||||
+ public static boolean throwOnPreventingTeleportAsync = true;
|
||||
|
||||
public static RegionFileFormat regionFormatName = RegionFileFormat.ANVIL;
|
||||
public static int regionFormatLinearCompressionLevel = 1;
|
||||
@@ -199,6 +201,8 @@ public class LuminolConfig {
|
||||
useVanillaRandomSource = get("fixes.use_vanilla_random_source",useVanillaRandomSource,"RNG feature related");
|
||||
fixLargePosMoving = get("fixes.fix_large_pos_moving", fixLargePosMoving,"Fix an entity moving issue on folia which is not fixed yet");
|
||||
warnOnLargeMovingDetected = get("fixes.warn_on_large_pos_moving",warnOnLargeMovingDetected);
|
||||
+ preventTeleportAsyncDuringMovingEvent = get("fixes.prevent_teleportasync_during_moving_event",preventTeleportAsyncDuringMovingEvent);
|
||||
+ throwOnPreventingTeleportAsync = get("fixes.throw_on_preventing_async_teleport",throwOnPreventingTeleportAsync);
|
||||
|
||||
regionFormatName = RegionFileFormat.fromString(get("save.region-format.format", regionFormatName.name()));
|
||||
if (regionFormatName.equals(RegionFileFormat.INVALID)) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index ea409d2a03c35990c6857c24305346a6ec7f4bf8..33d2205ba32dd1e11bba92e40d6a4125379b715f 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -326,6 +326,10 @@ public class ServerPlayer extends Player {
|
||||
public double lastEntitySpawnRadiusSquared = -1.0;
|
||||
// Paper end - optimise chunk tick iteration
|
||||
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ public boolean handlingMoveEvent = false;
|
||||
+ //Luminol end
|
||||
+
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
|
||||
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
|
||||
this.chatVisibility = ChatVisiblity.FULL;
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 18745ee33843d668613fd9e7f15d6a79f118280f..9f7eedbac2cbccba4e4cf5e0059cf3a4248438f1 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -688,7 +688,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
if (true) { // Spigot - don't skip any move events
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
+ this.player.handlingMoveEvent = true; //Luminol - Prevent teleportAsync calling during moving event being handled
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
+ this.player.handlingMoveEvent = false; //Luminol - Prevent teleportAsync calling during moving event being handled
|
||||
|
||||
// If the event is cancelled we move the player back to their old location.
|
||||
if (event.isCancelled()) {
|
||||
@@ -1592,7 +1594,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
if (from.getX() != Double.MAX_VALUE) {
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
+ this.player.handlingMoveEvent = true; //Luminol - Prevent teleportAsync calling during moving event being handled
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
+ this.player.handlingMoveEvent = false; //Luminol - Prevent teleportAsync calling during moving event being handled
|
||||
|
||||
// If the event is cancelled we move the player back to their old location.
|
||||
if (event.isCancelled()) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index e24b55dc96c2e3904e3c03d6bfa769aedf767b3b..1e5eb1277e1b4f2ba51fadbe2d882198ae940ae0 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3950,6 +3950,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
java.util.function.Consumer<Entity> teleportComplete) {
|
||||
io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot teleport entity async");
|
||||
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ if (this instanceof ServerPlayer player && LuminolConfig.preventTeleportAsyncDuringMovingEvent){
|
||||
+ if (player.handlingMoveEvent){
|
||||
+ if (LuminolConfig.throwOnPreventingTeleportAsync){
|
||||
+ throw new IllegalStateException("Player " + player.getScoreboardName() + " is trying to teleport to " + pos + " during move event handling!");
|
||||
+ }
|
||||
+ MinecraftServer.LOGGER.warn("Player {} is trying to teleport to {} during move event handling!",player.getScoreboardName(),pos);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
+
|
||||
if (!ServerLevel.isInSpawnableBounds(new BlockPos(io.papermc.paper.util.CoordinateUtils.getBlockX(pos), io.papermc.paper.util.CoordinateUtils.getBlockY(pos), io.papermc.paper.util.CoordinateUtils.getBlockZ(pos)))) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
index 44a6118d3bd67a95180f750c17967561946e2e87..d642f4d42ae7e73642929708a198294e4c5a24d4 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
|
||||
@@ -5,6 +5,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -20,6 +22,7 @@ import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
@@ -426,7 +429,21 @@ public abstract class AbstractMinecart extends Entity {
|
||||
this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle));
|
||||
|
||||
if (!from.equals(to)) {
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ for (Entity passenger : this.getPassengers()) {
|
||||
+ if (passenger instanceof ServerPlayer player){
|
||||
+ player.handlingMoveEvent = true;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to));
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ for (Entity passenger : this.getPassengers()) {
|
||||
+ if (passenger instanceof ServerPlayer player){
|
||||
+ player.handlingMoveEvent = false;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
|
||||
index 5c07da62c82bc70138f6cb5007629d6974be69ac..c68c84af56053cbf7f0c7809a16b60749a4fdd05 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
|
||||
@@ -2,6 +2,8 @@ package net.minecraft.world.entity.vehicle;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.IntFunction;
|
||||
@@ -16,6 +18,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
@@ -434,8 +437,22 @@ public class Boat extends Entity implements VariantHolder<Boat.Type> {
|
||||
server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle));
|
||||
|
||||
if (this.lastLocation != null && !this.lastLocation.equals(to)) {
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ for (Entity passenger : this.getPassengers()) {
|
||||
+ if (passenger instanceof ServerPlayer player){
|
||||
+ player.handlingMoveEvent = true;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
VehicleMoveEvent event = new VehicleMoveEvent(vehicle, this.lastLocation, to);
|
||||
server.getPluginManager().callEvent(event);
|
||||
+ //Luminol start - Prevent teleportAsync calling during moving event being handled
|
||||
+ for (Entity passenger : this.getPassengers()) {
|
||||
+ if (passenger instanceof ServerPlayer player){
|
||||
+ player.handlingMoveEvent = false;
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
}
|
||||
this.lastLocation = vehicle.getLocation();
|
||||
// CraftBukkit end
|
||||
BIN
public/image/Luminol_1.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
public/image/Luminol_2.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
public/image/Luminol_3.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/image/Luminol_4.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/image/Luminol_5.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/image/Luminol_6.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
32
public/image/SVG/Luminol_1.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="a" data-name="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 836.86 372.08">
|
||||
<rect width="836.86" height="372.08" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M123.68,248.4c4.92-4.92,9.64-9.76,14.54-14.41.74-.7,2.37-.74,3.56-.67,13.41.82,26.8,2.04,40.22,2.49,11.03.37,21.3-2.47,29.91-9.9,1.69-1.46,3.77-2.38,5.58-.43,1.87,2.02.4,3.96-.94,5.57-12.15,14.46-27.56,22.46-46.52,23.52-15.49.87-30.51-2.11-45.48-5.47-.16-.04-.29-.24-.85-.71Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M155.61,204.19c-.41-5.01-.78-10.02-1.23-15.03-1.08-12.23-1.58-24.44.87-36.58,2.24-11.14,7.8-20.1,17.35-26.45.5-.33.99-.84,1.53-.89,1.39-.14,3.27-.61,4.06.07.73.63.8,2.8.33,3.95-2.88,6.97-4.96,14.12-4.9,21.69.08,10.44.39,20.89.82,31.32.12,2.88-.4,5.05-2.58,7.11-5.2,4.91-10.16,10.07-15.22,15.13-.34-.11-.69-.22-1.03-.33Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M118.75,242.21c-1.32-7.02-2.75-13.2-3.6-19.46-1.57-11.63-3.06-23.25-1.52-35.06,2.05-15.79,9.85-28.09,22.06-37.89.61-.49,1.33-1.11,2.04-1.17,1.08-.1,2.6-.13,3.21.5.61.63.74,2.29.36,3.19-.56,1.32-1.78,2.35-2.7,3.52-7.24,9.07-9.87,19.58-9.5,30.96.42,12.92.9,25.85,1.51,38.76.16,3.32-.61,5.88-3.22,8.11-2.86,2.44-5.38,5.28-8.63,8.54Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M182.27,178.13c-.21-15.72-2.76-31.07,3.49-45.83,3.45-8.15,8.41-15.11,15.86-20.01,1.61-1.06,3.8-1.22,5.72-1.8-.2,1.85-.07,3.82-.65,5.54-2.26,6.68-3.26,13.5-3.05,20.53.18,5.76.39,11.53.38,17.29,0,1.47-.34,3.37-1.27,4.34-6.27,6.52-12.74,12.85-19.15,19.23-.19.19-.49.27-1.33.71Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M241.02,131.2c3.42-3.42,6.35-6.35,9.28-9.28.63-.63,1.26-1.27,1.84-1.95,1.59-1.87,2.16-3.99.34-5.9-1.94-2.04-4.13-1.15-5.82.45-3.81,3.62-7.46,7.4-11.81,11.75-.21-2.53-.57-4.35-.47-6.14.61-11.07,8.2-21.21,18.84-24.46,4.29-1.31,8.92-1.92,13.41-2.05,3.84-.11,6.08,2.41,6.31,6.24,1.08,17.79-12.05,33-29.85,31.68-.39-.03-.77-.13-2.06-.36Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M162.64,209.13c4.13-4.13,7.8-8,11.74-11.58.81-.73,2.64-.54,3.98-.45,8.44.55,16.87,1.61,25.3,1.68,6.5.05,13.19-.39,19.46-1.95,4.73-1.18,8.95-4.46,13.38-6.84.6-.32,1.07-1.06,1.68-1.17.99-.18,2.37-.38,2.99.14.59.5.86,2.12.49,2.87-.91,1.84-2.12,3.58-3.45,5.16-8.11,9.63-18.75,14.71-31.1,14.75-14,.05-28-1.2-42-1.91-.56-.03-1.1-.31-2.47-.71Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M199.32,172.64c5.32-5.32,10.01-10.13,14.87-14.76.79-.75,2.33-1,3.52-.98,9.13.13,18.26.43,27.4.55,2.47.03,4.94-.42,7.42-.57,3.8-.23,5.21,1.72,3.6,5.21-2.43,5.24-6.66,8.86-12.05,10.42-4.7,1.36-9.74,2.22-14.62,2.18-9.23-.07-18.45-.95-27.67-1.5-.47-.03-.94-.2-2.47-.54Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M212.27,148.64c-.74-13.61-1.76-26.62,5.71-38.42,3.05-4.82,7.19-8.46,12.11-11.21.88-.49,2.18-.26,3.28-.36-.15,1.08.04,2.4-.51,3.2-6.29,9.12-7.9,19.1-5.85,29.86.16.84-.04,2.11-.59,2.68-4.47,4.63-9.06,9.15-14.15,14.25Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M145.19,162.64c.11,2.23.21,4.47.34,6.7.81,13.7,1.67,27.39,2.36,41.1.07,1.36-.61,3.04-1.51,4.09-2.16,2.53-4.65,4.77-7.52,7.64-.41-6.67-.92-12.58-1.09-18.5-.22-7.75-.5-15.52-.12-23.26.21-4.29,1.48-8.59,2.73-12.75.6-2.01,2.26-3.69,3.44-5.53l1.37.51Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M146.47,225.36c2.62-2.62,4.86-4.98,7.25-7.17.56-.51,1.65-.7,2.47-.65,14.89.88,29.78,1.81,44.67,2.76.85.05,1.68.39,3.28.78-1.37,1.37-2.12,2.73-3.22,3.11-4.19,1.44-8.5,3.65-12.74,3.6-13.41-.16-26.8-1.21-40.2-1.92-.28-.01-.55-.18-1.52-.51Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M223.71,148.26c3.21-3.21,6.37-6.45,9.66-9.57.42-.4,1.49-.36,2.18-.19,10.45,2.44,20.08.53,29.05-5.26,2.06-.95,2.12-.32,3.2-.45-.03,1.08.33,2.37-.14,3.21-3.49,6.31-8.27,11.31-15.57,12.89-9.22,1.99-18.54,1.14-27.82.37-.19-.34-.38-.67-.57-1.01Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M96.66,222.12c-1.04-6.79-1.14-14.5.76-21.62.31-1.14,1.51-2.85,2.34-2.87,1.34-.03,3.19.79,3.93,1.86.94,1.37,1.3,3.33,1.38,5.07.64,13.75,2.61,27.31,5.35,40.77.19.91.18,1.86.33,3.53-5.42-4.74-9.39-9.59-11.15-15.87" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M231.81,183.69c-5.89,5.88-12.42,7.48-19.3,7.32-9.23-.21-18.45-.99-27.67-1.54-.36-.02-.71-.21-1.93-.58,2.94-2.94,5.45-5.56,8.11-8.02.54-.5,1.67-.56,2.5-.51,11.4.66,22.81,1.34,34.21,2.11,1.23.08,2.42.71,4.08,1.22Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M135.45,268.18c-6.86-1.92-12.66-5.42-16.69-11.4,13.99,2.98,27.85,5.4,42,5.81,1.69.05,3.52-.34,5.03.19,1.47.52,3.2,1.72,3.77,3.06.83,1.94-1.02,2.96-2.7,3.53-7.14,2.42-14.47,2.53-21.78,1.19" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M96.77,264.66c2.32-2.32,4.59-4.67,6.96-6.94,2.24-2.14,4.87-2.5,6.35-.82,1.96,2.22.94,4.34-.74,6.08-4.76,4.92-9.58,9.79-14.5,14.56-1.68,1.63-3.85,2.42-5.81.4-1.92-1.98-1.14-4.12.44-5.85,2.34-2.56,4.88-4.94,7.34-7.4l-.04-.04Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M310.13,149.94v81.38h33.8v9.62h-44.2v-91h10.4Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M353.94,211.3v-43.16h10.4v44.46c0,11.83,5.98,20.54,18.33,20.54s18.33-8.71,18.33-20.54v-44.46h10.4v43.16c0,19.89-10.53,31.2-28.73,31.2s-28.73-11.31-28.73-31.2Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M438.31,168.14v14.04c3.51-10.53,11.57-15.6,21.71-15.6s19.76,5.59,23.4,17.42c3.38-11.7,12.61-17.42,23.4-17.42,13.52,0,25.09,9.36,25.09,29.51v44.85h-10.4v-44.85c0-12.09-5.59-20.28-17.42-20.28-13,0-18.98,9.75-18.98,22.88v42.25h-10.4v-44.85c0-12.09-5.59-20.28-17.42-20.28-13,0-18.98,9.75-18.98,22.88v42.25h-10.4v-72.8h10.4Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M548.16,144.74h10.92v10.4h-10.92v-10.4ZM558.82,168.14v72.8h-10.4v-72.8h10.4Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M586.12,168.14v14.17c3.51-10.53,11.83-15.73,22.36-15.73,13.91,0,25.74,9.36,25.74,29.51v44.85h-10.4v-44.85c0-12.09-5.85-20.28-18.07-20.28-13.39,0-19.63,9.75-19.63,22.88v42.25h-10.4v-72.8h10.4Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M721.58,204.54c0,21.45-15.47,37.96-37.31,37.96s-37.31-16.51-37.31-37.96,15.47-37.96,37.31-37.96,37.31,16.51,37.31,37.96ZM684.27,233.15c16.51,0,26.91-12.48,26.91-28.6s-10.4-28.6-26.91-28.6-26.91,12.48-26.91,28.6,10.4,28.6,26.91,28.6Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M735.36,143.44h10.4v97.5h-10.4v-97.5Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
29
public/image/SVG/Luminol_2.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="f" data-name="6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 836.86 372.08">
|
||||
<g>
|
||||
<path d="M123.68,248.4c4.92-4.92,9.64-9.76,14.54-14.41.74-.7,2.37-.74,3.56-.67,13.41.82,26.8,2.04,40.22,2.49,11.03.37,21.3-2.47,29.91-9.9,1.69-1.46,3.77-2.38,5.58-.43,1.87,2.02.4,3.96-.94,5.57-12.15,14.46-27.56,22.46-46.52,23.52-15.49.87-30.51-2.11-45.48-5.47-.16-.04-.29-.24-.85-.71Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M155.61,204.19c-.41-5.01-.78-10.02-1.23-15.03-1.08-12.23-1.58-24.44.87-36.58,2.24-11.14,7.8-20.1,17.35-26.45.5-.33.99-.84,1.53-.89,1.39-.14,3.27-.61,4.06.07.73.63.8,2.8.33,3.95-2.88,6.97-4.96,14.12-4.9,21.69.08,10.44.39,20.89.82,31.32.12,2.88-.4,5.05-2.58,7.11-5.2,4.91-10.16,10.07-15.22,15.13-.34-.11-.69-.22-1.03-.33Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M118.75,242.21c-1.32-7.02-2.75-13.2-3.6-19.46-1.57-11.63-3.06-23.25-1.52-35.06,2.05-15.79,9.85-28.09,22.06-37.89.61-.49,1.33-1.11,2.04-1.17,1.08-.1,2.6-.13,3.21.5.61.63.74,2.29.36,3.19-.56,1.32-1.78,2.35-2.7,3.52-7.24,9.07-9.87,19.58-9.5,30.96.42,12.92.9,25.85,1.51,38.76.16,3.32-.61,5.88-3.22,8.11-2.86,2.44-5.38,5.28-8.63,8.54Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M182.27,178.13c-.21-15.72-2.76-31.07,3.49-45.83,3.45-8.15,8.41-15.11,15.86-20.01,1.61-1.06,3.8-1.22,5.72-1.8-.2,1.85-.07,3.82-.65,5.54-2.26,6.68-3.26,13.5-3.05,20.53.18,5.76.39,11.53.38,17.29,0,1.47-.34,3.37-1.27,4.34-6.27,6.52-12.74,12.85-19.15,19.23-.19.19-.49.27-1.33.71Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M241.02,131.2c3.42-3.42,6.35-6.35,9.28-9.28.63-.63,1.26-1.27,1.84-1.95,1.59-1.87,2.16-3.99.34-5.9-1.94-2.04-4.13-1.15-5.82.45-3.81,3.62-7.46,7.4-11.81,11.75-.21-2.53-.57-4.35-.47-6.14.61-11.07,8.2-21.21,18.84-24.46,4.29-1.31,8.92-1.92,13.41-2.05,3.84-.11,6.08,2.41,6.31,6.24,1.08,17.79-12.05,33-29.85,31.68-.39-.03-.77-.13-2.06-.36Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M162.64,209.13c4.13-4.13,7.8-8,11.74-11.58.81-.73,2.64-.54,3.98-.45,8.44.55,16.87,1.61,25.3,1.68,6.5.05,13.19-.39,19.46-1.95,4.73-1.18,8.95-4.46,13.38-6.84.6-.32,1.07-1.06,1.68-1.17.99-.18,2.37-.38,2.99.14.59.5.86,2.12.49,2.87-.91,1.84-2.12,3.58-3.45,5.16-8.11,9.63-18.75,14.71-31.1,14.75-14,.05-28-1.2-42-1.91-.56-.03-1.1-.31-2.47-.71Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M199.32,172.64c5.32-5.32,10.01-10.13,14.87-14.76.79-.75,2.33-1,3.52-.98,9.13.13,18.26.43,27.4.55,2.47.03,4.94-.42,7.42-.57,3.8-.23,5.21,1.72,3.6,5.21-2.43,5.24-6.66,8.86-12.05,10.42-4.7,1.36-9.74,2.22-14.62,2.18-9.23-.07-18.45-.95-27.67-1.5-.47-.03-.94-.2-2.47-.54Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M212.27,148.64c-.74-13.61-1.76-26.62,5.71-38.42,3.05-4.82,7.19-8.46,12.11-11.21.88-.49,2.18-.26,3.28-.36-.15,1.08.04,2.4-.51,3.2-6.29,9.12-7.9,19.1-5.85,29.86.16.84-.04,2.11-.59,2.68-4.47,4.63-9.06,9.15-14.15,14.25Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M145.19,162.64c.11,2.23.21,4.47.34,6.7.81,13.7,1.67,27.39,2.36,41.1.07,1.36-.61,3.04-1.51,4.09-2.16,2.53-4.65,4.77-7.52,7.64-.41-6.67-.92-12.58-1.09-18.5-.22-7.75-.5-15.52-.12-23.26.21-4.29,1.48-8.59,2.73-12.75.6-2.01,2.26-3.69,3.44-5.53l1.37.51Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M146.47,225.36c2.62-2.62,4.86-4.98,7.25-7.17.56-.51,1.65-.7,2.47-.65,14.89.88,29.78,1.81,44.67,2.76.85.05,1.68.39,3.28.78-1.37,1.37-2.12,2.73-3.22,3.11-4.19,1.44-8.5,3.65-12.74,3.6-13.41-.16-26.8-1.21-40.2-1.92-.28-.01-.55-.18-1.52-.51Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M223.71,148.26c3.21-3.21,6.37-6.45,9.66-9.57.42-.4,1.49-.36,2.18-.19,10.45,2.44,20.08.53,29.05-5.26,2.06-.95,2.12-.32,3.2-.45-.03,1.08.33,2.37-.14,3.21-3.49,6.31-8.27,11.31-15.57,12.89-9.22,1.99-18.54,1.14-27.82.37-.19-.34-.38-.67-.57-1.01Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M96.66,222.12c-1.04-6.79-1.14-14.5.76-21.62.31-1.14,1.51-2.85,2.34-2.87,1.34-.03,3.19.79,3.93,1.86.94,1.37,1.3,3.33,1.38,5.07.64,13.75,2.61,27.31,5.35,40.77.19.91.18,1.86.33,3.53-5.42-4.74-9.39-9.59-11.15-15.87" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M231.81,183.69c-5.89,5.88-12.42,7.48-19.3,7.32-9.23-.21-18.45-.99-27.67-1.54-.36-.02-.71-.21-1.93-.58,2.94-2.94,5.45-5.56,8.11-8.02.54-.5,1.67-.56,2.5-.51,11.4.66,22.81,1.34,34.21,2.11,1.23.08,2.42.71,4.08,1.22Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M135.45,268.18c-6.86-1.92-12.66-5.42-16.69-11.4,13.99,2.98,27.85,5.4,42,5.81,1.69.05,3.52-.34,5.03.19,1.47.52,3.2,1.72,3.77,3.06.83,1.94-1.02,2.96-2.7,3.53-7.14,2.42-14.47,2.53-21.78,1.19" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M96.77,264.66c2.32-2.32,4.59-4.67,6.96-6.94,2.24-2.14,4.87-2.5,6.35-.82,1.96,2.22.94,4.34-.74,6.08-4.76,4.92-9.58,9.79-14.5,14.56-1.68,1.63-3.85,2.42-5.81.4-1.92-1.98-1.14-4.12.44-5.85,2.34-2.56,4.88-4.94,7.34-7.4l-.04-.04Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M310.13,149.94v81.38h33.8v9.62h-44.2v-91h10.4Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M353.94,211.3v-43.16h10.4v44.46c0,11.83,5.98,20.54,18.33,20.54s18.33-8.71,18.33-20.54v-44.46h10.4v43.16c0,19.89-10.53,31.2-28.73,31.2s-28.73-11.31-28.73-31.2Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M438.31,168.14v14.04c3.51-10.53,11.57-15.6,21.71-15.6s19.76,5.59,23.4,17.42c3.38-11.7,12.61-17.42,23.4-17.42,13.52,0,25.09,9.36,25.09,29.51v44.85h-10.4v-44.85c0-12.09-5.59-20.28-17.42-20.28-13,0-18.98,9.75-18.98,22.88v42.25h-10.4v-44.85c0-12.09-5.59-20.28-17.42-20.28-13,0-18.98,9.75-18.98,22.88v42.25h-10.4v-72.8h10.4Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M548.16,144.74h10.92v10.4h-10.92v-10.4ZM558.82,168.14v72.8h-10.4v-72.8h10.4Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M586.12,168.14v14.17c3.51-10.53,11.83-15.73,22.36-15.73,13.91,0,25.74,9.36,25.74,29.51v44.85h-10.4v-44.85c0-12.09-5.85-20.28-18.07-20.28-13.39,0-19.63,9.75-19.63,22.88v42.25h-10.4v-72.8h10.4Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M721.58,204.54c0,21.45-15.47,37.96-37.31,37.96s-37.31-16.51-37.31-37.96,15.47-37.96,37.31-37.96,37.31,16.51,37.31,37.96ZM684.27,233.15c16.51,0,26.91-12.48,26.91-28.6s-10.4-28.6-26.91-28.6-26.91,12.48-26.91,28.6,10.4,28.6,26.91,28.6Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M735.36,143.44h10.4v97.5h-10.4v-97.5Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
30
public/image/SVG/Luminol_3.svg
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="b" data-name="2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 287.08 287.08">
|
||||
<rect x="0" width="287.08" height="287.08" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<g>
|
||||
<path d="M45.03,194.01v37.56h15.6v4.44h-20.4v-42h4.8Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M65.25,222.33v-19.92h4.8v20.52c0,5.46,2.76,9.48,8.46,9.48s8.46-4.02,8.46-9.48v-20.52h4.8v19.92c0,9.18-4.86,14.4-13.26,14.4s-13.26-5.22-13.26-14.4Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M104.19,202.41v6.48c1.62-4.86,5.34-7.2,10.02-7.2s9.12,2.58,10.8,8.04c1.56-5.4,5.82-8.04,10.8-8.04,6.24,0,11.58,4.32,11.58,13.62v20.7h-4.8v-20.7c0-5.58-2.58-9.36-8.04-9.36-6,0-8.76,4.5-8.76,10.56v19.5h-4.8v-20.7c0-5.58-2.58-9.36-8.04-9.36-6,0-8.76,4.5-8.76,10.56v19.5h-4.8v-33.6h4.8Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M154.89,191.61h5.04v4.8h-5.04v-4.8ZM159.81,202.41v33.6h-4.8v-33.6h4.8Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M172.41,202.41v6.54c1.62-4.86,5.46-7.26,10.32-7.26,6.42,0,11.88,4.32,11.88,13.62v20.7h-4.8v-20.7c0-5.58-2.7-9.36-8.34-9.36-6.18,0-9.06,4.5-9.06,10.56v19.5h-4.8v-33.6h4.8Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M234.93,219.21c0,9.9-7.14,17.52-17.22,17.52s-17.22-7.62-17.22-17.52,7.14-17.52,17.22-17.52,17.22,7.62,17.22,17.52ZM217.71,232.41c7.62,0,12.42-5.76,12.42-13.2s-4.8-13.2-12.42-13.2-12.42,5.76-12.42,13.2,4.8,13.2,12.42,13.2Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M241.29,191.01h4.8v45h-4.8v-45Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M109.11,163.11c3.48-3.48,6.81-6.9,10.27-10.18.53-.5,1.67-.52,2.51-.47,9.47.58,18.93,1.44,28.41,1.76,7.79.26,15.04-1.74,21.13-6.99,1.2-1.03,2.66-1.68,3.94-.3,1.32,1.43.28,2.8-.67,3.93-8.58,10.21-19.47,15.86-32.86,16.62-10.95.62-21.55-1.49-32.13-3.86-.12-.03-.21-.17-.6-.5Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M131.67,131.88c-.29-3.54-.55-7.08-.87-10.62-.77-8.64-1.11-17.26.61-25.84,1.58-7.87,5.51-14.2,12.25-18.68.35-.23.7-.59,1.08-.63.98-.1,2.31-.43,2.87.05.52.45.57,1.98.23,2.79-2.03,4.92-3.5,9.98-3.46,15.32.06,7.38.27,14.75.58,22.12.08,2.04-.28,3.57-1.82,5.03-3.67,3.47-7.18,7.11-10.75,10.69-.24-.08-.48-.16-.73-.23Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M105.63,158.74c-.93-4.96-1.94-9.32-2.54-13.74-1.11-8.21-2.16-16.43-1.07-24.77,1.45-11.15,6.96-19.84,15.58-26.76.43-.35.94-.78,1.44-.83.77-.07,1.83-.09,2.26.35.43.45.52,1.62.25,2.25-.4.93-1.26,1.66-1.91,2.48-5.11,6.41-6.97,13.83-6.71,21.87.3,9.13.64,18.26,1.07,27.38.11,2.34-.43,4.15-2.27,5.73-2.02,1.73-3.8,3.73-6.1,6.03Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M150.5,113.47c-.15-11.1-1.95-21.95,2.47-32.38,2.44-5.76,5.94-10.67,11.2-14.13,1.13-.75,2.68-.86,4.04-1.27-.14,1.31-.05,2.7-.46,3.92-1.6,4.72-2.3,9.54-2.15,14.5.12,4.07.28,8.14.27,12.21,0,1.04-.24,2.38-.9,3.07-4.43,4.61-9,9.08-13.53,13.58-.13.13-.34.19-.94.5Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M192,80.32c2.42-2.42,4.49-4.48,6.55-6.56.45-.45.89-.9,1.3-1.38,1.12-1.32,1.53-2.82.24-4.17-1.37-1.44-2.92-.81-4.11.32-2.69,2.55-5.27,5.23-8.34,8.3-.15-1.79-.4-3.07-.33-4.33.43-7.82,5.79-14.98,13.31-17.28,3.03-.93,6.3-1.36,9.48-1.45,2.72-.08,4.29,1.7,4.46,4.41.76,12.57-8.51,23.31-21.09,22.38-.27-.02-.54-.09-1.46-.25Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M136.63,135.37c2.92-2.92,5.51-5.65,8.3-8.18.57-.52,1.86-.38,2.81-.32,5.96.39,11.91,1.14,17.88,1.19,4.59.04,9.32-.27,13.74-1.37,3.34-.83,6.32-3.15,9.45-4.83.43-.23.76-.75,1.19-.83.7-.13,1.68-.27,2.11.1.42.35.61,1.5.35,2.02-.64,1.3-1.5,2.53-2.44,3.65-5.73,6.81-13.24,10.39-21.97,10.42-9.89.03-19.78-.85-29.67-1.35-.39-.02-.78-.22-1.74-.5Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M162.55,109.59c3.75-3.75,7.07-7.15,10.51-10.42.56-.53,1.65-.71,2.49-.69,6.45.09,12.9.3,19.35.39,1.75.02,3.49-.3,5.24-.4,2.68-.16,3.68,1.22,2.54,3.68-1.72,3.7-4.7,6.26-8.51,7.36-3.32.96-6.88,1.57-10.33,1.54-6.52-.05-13.03-.67-19.55-1.06-.33-.02-.66-.14-1.75-.38Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M171.69,92.64c-.52-9.61-1.24-18.81,4.03-27.14,2.15-3.4,5.08-5.97,8.55-7.92.62-.35,1.54-.18,2.32-.25-.11.76.03,1.7-.36,2.26-4.44,6.45-5.58,13.49-4.13,21.09.11.6-.03,1.49-.42,1.89-3.16,3.27-6.4,6.46-10,10.06Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M124.31,102.53c.08,1.58.15,3.16.24,4.73.57,9.68,1.18,19.35,1.67,29.03.05.96-.43,2.15-1.07,2.89-1.53,1.79-3.29,3.37-5.31,5.4-.29-4.71-.65-8.89-.77-13.07-.16-5.47-.35-10.97-.08-16.43.15-3.03,1.05-6.07,1.93-9.01.43-1.42,1.6-2.61,2.43-3.9l.97.36Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M125.21,146.83c1.85-1.85,3.44-3.52,5.12-5.06.4-.36,1.17-.49,1.75-.46,10.52.62,21.04,1.28,31.56,1.95.6.04,1.18.27,2.32.55-.97.97-1.5,1.93-2.27,2.2-2.96,1.02-6,2.58-9,2.54-9.47-.11-18.93-.85-28.4-1.36-.2-.01-.39-.13-1.07-.36Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M179.77,92.37c2.26-2.26,4.5-4.55,6.82-6.76.3-.28,1.05-.25,1.54-.14,7.39,1.73,14.18.37,20.52-3.71,1.46-.67,1.5-.22,2.26-.32-.02.76.23,1.68-.1,2.27-2.47,4.45-5.85,7.99-11,9.11-6.52,1.41-13.1.81-19.65.26-.13-.24-.27-.48-.4-.71Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M90.03,144.54c-.74-4.8-.81-10.24.53-15.28.22-.81,1.07-2.02,1.65-2.03.94-.02,2.25.55,2.78,1.31.67.97.92,2.35.98,3.58.45,9.71,1.84,19.29,3.78,28.8.13.64.13,1.31.23,2.49-3.83-3.35-6.63-6.77-7.88-11.21" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M185.5,117.4c-4.16,4.15-8.77,5.28-13.63,5.17-6.52-.15-13.03-.7-19.54-1.09-.26-.02-.5-.15-1.36-.41,2.08-2.08,3.85-3.93,5.73-5.66.38-.35,1.18-.4,1.77-.36,8.06.46,16.11.95,24.16,1.49.87.06,1.71.5,2.88.86Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M117.43,177.08c-4.85-1.36-8.94-3.83-11.79-8.05,9.88,2.11,19.67,3.81,29.67,4.11,1.19.03,2.48-.24,3.55.13,1.04.37,2.26,1.21,2.66,2.16.58,1.37-.72,2.09-1.91,2.49-5.05,1.71-10.22,1.79-15.39.84" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M90.1,174.6c1.64-1.64,3.24-3.3,4.92-4.9,1.58-1.51,3.44-1.77,4.49-.58,1.39,1.57.67,3.07-.52,4.3-3.36,3.48-6.77,6.92-10.24,10.29-1.19,1.15-2.72,1.71-4.1.29-1.35-1.4-.81-2.91.31-4.13,1.65-1.81,3.45-3.49,5.19-5.23l-.03-.03Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
21
public/image/SVG/Luminol_4.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="c" data-name="3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 287.08 287.08">
|
||||
<rect width="287.08" height="287.08" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<g>
|
||||
<path d="M92.91,203.79c4.69-4.69,9.19-9.31,13.87-13.74.71-.67,2.26-.71,3.39-.64,12.79.78,25.56,1.94,38.36,2.37,10.52.36,20.31-2.35,28.53-9.44,1.61-1.39,3.59-2.27,5.32-.41,1.78,1.92.38,3.78-.9,5.31-11.59,13.79-26.29,21.42-44.38,22.44-14.78.83-29.1-2.01-43.38-5.21-.16-.04-.28-.22-.81-.68Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M123.36,161.63c-.39-4.78-.75-9.56-1.17-14.33-1.03-11.66-1.5-23.31.83-34.89,2.14-10.62,7.44-19.17,16.55-25.23.47-.31.95-.8,1.46-.85,1.32-.13,3.12-.59,3.88.07.7.6.76,2.67.31,3.77-2.75,6.65-4.73,13.47-4.68,20.69.07,9.96.37,19.92.78,29.87.11,2.75-.38,4.82-2.46,6.79-4.96,4.69-9.69,9.6-14.52,14.43-.33-.11-.65-.21-.98-.32Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M88.21,197.89c-1.26-6.7-2.62-12.59-3.43-18.56-1.5-11.09-2.92-22.18-1.45-33.45,1.96-15.06,9.4-26.79,21.04-36.14.59-.47,1.27-1.06,1.95-1.12,1.03-.09,2.48-.12,3.06.48.58.6.71,2.19.34,3.04-.54,1.26-1.69,2.25-2.58,3.35-6.9,8.65-9.41,18.68-9.06,29.54.4,12.33.86,24.65,1.44,36.97.15,3.16-.58,5.61-3.07,7.74-2.73,2.33-5.13,5.04-8.23,8.14Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M148.8,136.77c-.2-14.99-2.63-29.64,3.33-43.72,3.29-7.77,8.02-14.41,15.12-19.08,1.53-1.01,3.62-1.17,5.46-1.72-.19,1.77-.07,3.64-.62,5.29-2.16,6.37-3.11,12.88-2.91,19.58.17,5.5.37,11,.36,16.49,0,1.4-.32,3.21-1.21,4.14-5.98,6.22-12.15,12.25-18.27,18.34-.18.18-.46.25-1.27.68Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M204.83,92c3.27-3.27,6.06-6.06,8.85-8.85.6-.6,1.2-1.21,1.75-1.86,1.52-1.79,2.06-3.8.32-5.63-1.85-1.95-3.94-1.09-5.55.43-3.63,3.45-7.12,7.06-11.27,11.21-.2-2.41-.55-4.14-.45-5.85.58-10.56,7.82-20.23,17.97-23.33,4.09-1.25,8.51-1.83,12.79-1.95,3.67-.1,5.8,2.3,6.02,5.95,1.03,16.97-11.49,31.48-28.47,30.22-.37-.03-.73-.12-1.97-.34Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M130.07,166.33c3.94-3.94,7.44-7.63,11.2-11.04.77-.7,2.52-.51,3.8-.43,8.05.53,16.09,1.54,24.14,1.6,6.2.05,12.58-.37,18.56-1.86,4.52-1.12,8.53-4.25,12.76-6.52.58-.31,1.02-1.01,1.6-1.12.95-.17,2.26-.36,2.85.13.56.47.82,2.02.47,2.73-.87,1.76-2.02,3.42-3.29,4.93-7.74,9.19-17.88,14.03-29.66,14.07-13.35.05-26.71-1.15-40.06-1.82-.53-.03-1.05-.29-2.36-.68Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M165.06,131.53c5.07-5.07,9.55-9.66,14.19-14.08.75-.72,2.23-.95,3.36-.94,8.71.12,17.42.41,26.13.52,2.36.03,4.72-.41,7.08-.55,3.62-.22,4.97,1.64,3.43,4.97-2.32,5-6.35,8.45-11.49,9.94-4.49,1.3-9.29,2.12-13.95,2.08-8.8-.07-17.6-.9-26.39-1.43-.45-.03-.89-.19-2.36-.52Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M177.41,108.64c-.71-12.98-1.68-25.39,5.45-36.64,2.91-4.59,6.86-8.07,11.55-10.69.84-.47,2.08-.24,3.13-.34-.15,1.03.04,2.29-.49,3.06-6,8.7-7.54,18.22-5.58,28.48.15.8-.04,2.01-.56,2.55-4.26,4.42-8.64,8.73-13.5,13.59Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M113.43,121.99c.11,2.13.2,4.26.32,6.39.77,13.07,1.59,26.13,2.25,39.2.06,1.29-.59,2.9-1.44,3.91-2.06,2.41-4.44,4.55-7.17,7.28-.39-6.36-.88-12-1.04-17.65-.21-7.39-.48-14.81-.11-22.18.2-4.1,1.41-8.2,2.6-12.17.57-1.91,2.15-3.52,3.28-5.27l1.31.49Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M114.65,181.82c2.5-2.5,4.64-4.75,6.92-6.84.54-.49,1.57-.67,2.36-.62,14.21.84,28.41,1.73,42.61,2.64.81.05,1.6.37,3.13.74-1.31,1.31-2.03,2.61-3.07,2.97-4,1.37-8.11,3.48-12.15,3.43-12.79-.15-25.57-1.15-38.35-1.83-.27-.01-.53-.17-1.45-.49Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M188.32,108.28c3.06-3.06,6.08-6.15,9.21-9.13.4-.38,1.42-.34,2.08-.19,9.97,2.33,19.15.5,27.71-5.01,1.97-.91,2.03-.3,3.06-.43-.03,1.03.31,2.26-.13,3.07-3.33,6.01-7.89,10.79-14.85,12.29-8.8,1.9-17.69,1.09-26.54.35-.18-.32-.36-.64-.54-.96Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M67.14,178.73c-.99-6.48-1.09-13.83.72-20.63.29-1.09,1.44-2.72,2.23-2.74,1.28-.03,3.04.75,3.75,1.77.9,1.3,1.24,3.18,1.32,4.83.61,13.11,2.49,26.05,5.11,38.89.18.87.17,1.77.32,3.36-5.17-4.52-8.95-9.14-10.64-15.14" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M196.05,142.07c-5.62,5.61-11.85,7.13-18.41,6.99-8.8-.2-17.59-.94-26.39-1.47-.34-.02-.68-.2-1.84-.55,2.81-2.81,5.2-5.31,7.74-7.65.52-.48,1.59-.54,2.39-.49,10.88.63,21.75,1.28,32.63,2.01,1.17.08,2.31.67,3.89,1.16Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M104.14,222.66c-6.55-1.83-12.07-5.17-15.92-10.87,13.35,2.84,26.56,5.15,40.06,5.54,1.61.05,3.35-.33,4.79.18,1.4.5,3.05,1.64,3.6,2.92.79,1.85-.98,2.82-2.58,3.37-6.81,2.31-13.81,2.41-20.78,1.14" style="fill: #fff; stroke-width: 0px;"/>
|
||||
<path d="M67.24,219.31c2.21-2.21,4.38-4.46,6.64-6.62,2.14-2.04,4.64-2.39,6.06-.79,1.87,2.12.9,4.14-.71,5.8-4.54,4.69-9.14,9.34-13.83,13.89-1.6,1.55-3.67,2.31-5.54.39-1.83-1.88-1.09-3.93.42-5.58,2.23-2.44,4.66-4.71,7-7.06l-.04-.04Z" style="fill: #fff; stroke-width: 0px;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
29
public/image/SVG/Luminol_5.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="d" data-name="4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 287.08 287.08">
|
||||
<g>
|
||||
<path d="M45.03,194.01v37.56h15.6v4.44h-20.4v-42h4.8Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M65.25,222.33v-19.92h4.8v20.52c0,5.46,2.76,9.48,8.46,9.48s8.46-4.02,8.46-9.48v-20.52h4.8v19.92c0,9.18-4.86,14.4-13.26,14.4s-13.26-5.22-13.26-14.4Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M104.19,202.41v6.48c1.62-4.86,5.34-7.2,10.02-7.2s9.12,2.58,10.8,8.04c1.56-5.4,5.82-8.04,10.8-8.04,6.24,0,11.58,4.32,11.58,13.62v20.7h-4.8v-20.7c0-5.58-2.58-9.36-8.04-9.36-6,0-8.76,4.5-8.76,10.56v19.5h-4.8v-20.7c0-5.58-2.58-9.36-8.04-9.36-6,0-8.76,4.5-8.76,10.56v19.5h-4.8v-33.6h4.8Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M154.89,191.61h5.04v4.8h-5.04v-4.8ZM159.81,202.41v33.6h-4.8v-33.6h4.8Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M172.41,202.41v6.54c1.62-4.86,5.46-7.26,10.32-7.26,6.42,0,11.88,4.32,11.88,13.62v20.7h-4.8v-20.7c0-5.58-2.7-9.36-8.34-9.36-6.18,0-9.06,4.5-9.06,10.56v19.5h-4.8v-33.6h4.8Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M234.93,219.21c0,9.9-7.14,17.52-17.22,17.52s-17.22-7.62-17.22-17.52,7.14-17.52,17.22-17.52,17.22,7.62,17.22,17.52ZM217.71,232.41c7.62,0,12.42-5.76,12.42-13.2s-4.8-13.2-12.42-13.2-12.42,5.76-12.42,13.2,4.8,13.2,12.42,13.2Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M241.29,191.01h4.8v45h-4.8v-45Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M109.11,163.11c3.48-3.48,6.81-6.9,10.27-10.18.53-.5,1.67-.52,2.51-.47,9.47.58,18.93,1.44,28.41,1.76,7.79.26,15.04-1.74,21.13-6.99,1.2-1.03,2.66-1.68,3.94-.3,1.32,1.43.28,2.8-.67,3.93-8.58,10.21-19.47,15.86-32.86,16.62-10.95.62-21.55-1.49-32.13-3.86-.12-.03-.21-.17-.6-.5Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M131.67,131.88c-.29-3.54-.55-7.08-.87-10.62-.77-8.64-1.11-17.26.61-25.84,1.58-7.87,5.51-14.2,12.25-18.68.35-.23.7-.59,1.08-.63.98-.1,2.31-.43,2.87.05.52.45.57,1.98.23,2.79-2.03,4.92-3.5,9.98-3.46,15.32.06,7.38.27,14.75.58,22.12.08,2.04-.28,3.57-1.82,5.03-3.67,3.47-7.18,7.11-10.75,10.69-.24-.08-.48-.16-.73-.23Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M105.63,158.74c-.93-4.96-1.94-9.32-2.54-13.74-1.11-8.21-2.16-16.43-1.07-24.77,1.45-11.15,6.96-19.84,15.58-26.76.43-.35.94-.78,1.44-.83.77-.07,1.83-.09,2.26.35.43.45.52,1.62.25,2.25-.4.93-1.26,1.66-1.91,2.48-5.11,6.41-6.97,13.83-6.71,21.87.3,9.13.64,18.26,1.07,27.38.11,2.34-.43,4.15-2.27,5.73-2.02,1.73-3.8,3.73-6.1,6.03Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M150.5,113.47c-.15-11.1-1.95-21.95,2.47-32.38,2.44-5.76,5.94-10.67,11.2-14.13,1.13-.75,2.68-.86,4.04-1.27-.14,1.31-.05,2.7-.46,3.92-1.6,4.72-2.3,9.54-2.15,14.5.12,4.07.28,8.14.27,12.21,0,1.04-.24,2.38-.9,3.07-4.43,4.61-9,9.08-13.53,13.58-.13.13-.34.19-.94.5Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M192,80.32c2.42-2.42,4.49-4.48,6.55-6.56.45-.45.89-.9,1.3-1.38,1.12-1.32,1.53-2.82.24-4.17-1.37-1.44-2.92-.81-4.11.32-2.69,2.55-5.27,5.23-8.34,8.3-.15-1.79-.4-3.07-.33-4.33.43-7.82,5.79-14.98,13.31-17.28,3.03-.93,6.3-1.36,9.48-1.45,2.72-.08,4.29,1.7,4.46,4.41.76,12.57-8.51,23.31-21.09,22.38-.27-.02-.54-.09-1.46-.25Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M136.63,135.37c2.92-2.92,5.51-5.65,8.3-8.18.57-.52,1.86-.38,2.81-.32,5.96.39,11.91,1.14,17.88,1.19,4.59.04,9.32-.27,13.74-1.37,3.34-.83,6.32-3.15,9.45-4.83.43-.23.76-.75,1.19-.83.7-.13,1.68-.27,2.11.1.42.35.61,1.5.35,2.02-.64,1.3-1.5,2.53-2.44,3.65-5.73,6.81-13.24,10.39-21.97,10.42-9.89.03-19.78-.85-29.67-1.35-.39-.02-.78-.22-1.74-.5Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M162.55,109.59c3.75-3.75,7.07-7.15,10.51-10.42.56-.53,1.65-.71,2.49-.69,6.45.09,12.9.3,19.35.39,1.75.02,3.49-.3,5.24-.4,2.68-.16,3.68,1.22,2.54,3.68-1.72,3.7-4.7,6.26-8.51,7.36-3.32.96-6.88,1.57-10.33,1.54-6.52-.05-13.03-.67-19.55-1.06-.33-.02-.66-.14-1.75-.38Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M171.69,92.64c-.52-9.61-1.24-18.81,4.03-27.14,2.15-3.4,5.08-5.97,8.55-7.92.62-.35,1.54-.18,2.32-.25-.11.76.03,1.7-.36,2.26-4.44,6.45-5.58,13.49-4.13,21.09.11.6-.03,1.49-.42,1.89-3.16,3.27-6.4,6.46-10,10.06Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M124.31,102.53c.08,1.58.15,3.16.24,4.73.57,9.68,1.18,19.35,1.67,29.03.05.96-.43,2.15-1.07,2.89-1.53,1.79-3.29,3.37-5.31,5.4-.29-4.71-.65-8.89-.77-13.07-.16-5.47-.35-10.97-.08-16.43.15-3.03,1.05-6.07,1.93-9.01.43-1.42,1.6-2.61,2.43-3.9l.97.36Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M125.21,146.83c1.85-1.85,3.44-3.52,5.12-5.06.4-.36,1.17-.49,1.75-.46,10.52.62,21.04,1.28,31.56,1.95.6.04,1.18.27,2.32.55-.97.97-1.5,1.93-2.27,2.2-2.96,1.02-6,2.58-9,2.54-9.47-.11-18.93-.85-28.4-1.36-.2-.01-.39-.13-1.07-.36Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M179.77,92.37c2.26-2.26,4.5-4.55,6.82-6.76.3-.28,1.05-.25,1.54-.14,7.39,1.73,14.18.37,20.52-3.71,1.46-.67,1.5-.22,2.26-.32-.02.76.23,1.68-.1,2.27-2.47,4.45-5.85,7.99-11,9.11-6.52,1.41-13.1.81-19.65.26-.13-.24-.27-.48-.4-.71Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M90.03,144.54c-.74-4.8-.81-10.24.53-15.28.22-.81,1.07-2.02,1.65-2.03.94-.02,2.25.55,2.78,1.31.67.97.92,2.35.98,3.58.45,9.71,1.84,19.29,3.78,28.8.13.64.13,1.31.23,2.49-3.83-3.35-6.63-6.77-7.88-11.21" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M185.5,117.4c-4.16,4.15-8.77,5.28-13.63,5.17-6.52-.15-13.03-.7-19.54-1.09-.26-.02-.5-.15-1.36-.41,2.08-2.08,3.85-3.93,5.73-5.66.38-.35,1.18-.4,1.77-.36,8.06.46,16.11.95,24.16,1.49.87.06,1.71.5,2.88.86Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M117.43,177.08c-4.85-1.36-8.94-3.83-11.79-8.05,9.88,2.11,19.67,3.81,29.67,4.11,1.19.03,2.48-.24,3.55.13,1.04.37,2.26,1.21,2.66,2.16.58,1.37-.72,2.09-1.91,2.49-5.05,1.71-10.22,1.79-15.39.84" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M90.1,174.6c1.64-1.64,3.24-3.3,4.92-4.9,1.58-1.51,3.44-1.77,4.49-.58,1.39,1.57.67,3.07-.52,4.3-3.36,3.48-6.77,6.92-10.24,10.29-1.19,1.15-2.72,1.71-4.1.29-1.35-1.4-.81-2.91.31-4.13,1.65-1.81,3.45-3.49,5.19-5.23l-.03-.03Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
18
public/image/SVG/Luminol_6.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="e" data-name="5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 287.08 287.08">
|
||||
<path d="M92.91,205.18c4.69-4.69,9.19-9.31,13.87-13.74.71-.67,2.26-.71,3.39-.64,12.79.78,25.56,1.94,38.36,2.37,10.52.36,20.31-2.35,28.53-9.44,1.61-1.39,3.59-2.27,5.32-.41,1.78,1.92.38,3.78-.9,5.31-11.59,13.79-26.29,21.42-44.38,22.44-14.78.83-29.1-2.01-43.38-5.21-.16-.04-.28-.22-.81-.68Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M123.36,163.01c-.39-4.78-.75-9.56-1.17-14.33-1.03-11.66-1.5-23.31.83-34.89,2.14-10.62,7.44-19.17,16.55-25.23.47-.31.95-.8,1.46-.85,1.32-.13,3.12-.59,3.88.07.7.6.76,2.67.31,3.77-2.75,6.65-4.73,13.47-4.68,20.69.07,9.96.37,19.92.78,29.87.11,2.75-.38,4.82-2.46,6.79-4.96,4.69-9.69,9.6-14.52,14.43-.33-.11-.65-.21-.98-.32Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M88.21,199.28c-1.26-6.7-2.62-12.59-3.43-18.56-1.5-11.09-2.92-22.18-1.45-33.45,1.96-15.06,9.4-26.79,21.04-36.14.59-.47,1.27-1.06,1.95-1.12,1.03-.09,2.48-.12,3.06.48.58.6.71,2.19.34,3.04-.54,1.26-1.69,2.25-2.58,3.35-6.9,8.65-9.41,18.68-9.06,29.54.4,12.33.86,24.65,1.44,36.97.15,3.16-.58,5.61-3.07,7.74-2.73,2.33-5.13,5.04-8.23,8.14Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M148.8,138.15c-.2-14.99-2.63-29.64,3.33-43.72,3.29-7.77,8.02-14.41,15.12-19.08,1.53-1.01,3.62-1.17,5.46-1.72-.19,1.77-.07,3.64-.62,5.29-2.16,6.37-3.11,12.88-2.91,19.58.17,5.5.37,11,.36,16.49,0,1.4-.32,3.21-1.21,4.14-5.98,6.22-12.15,12.25-18.27,18.34-.18.18-.46.25-1.27.68Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M204.83,93.39c3.27-3.27,6.06-6.06,8.85-8.85.6-.6,1.2-1.21,1.75-1.86,1.52-1.79,2.06-3.8.32-5.63-1.85-1.95-3.94-1.09-5.55.43-3.63,3.45-7.12,7.06-11.27,11.21-.2-2.41-.55-4.14-.45-5.85.58-10.56,7.82-20.23,17.97-23.33,4.09-1.25,8.51-1.83,12.79-1.95,3.67-.1,5.8,2.3,6.02,5.95,1.03,16.97-11.49,31.48-28.47,30.22-.37-.03-.73-.12-1.97-.34Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M130.07,167.72c3.94-3.94,7.44-7.63,11.2-11.04.77-.7,2.52-.51,3.8-.43,8.05.53,16.09,1.54,24.14,1.6,6.2.05,12.58-.37,18.56-1.86,4.52-1.12,8.53-4.25,12.76-6.52.58-.31,1.02-1.01,1.6-1.12.95-.17,2.26-.36,2.85.13.56.47.82,2.02.47,2.73-.87,1.76-2.02,3.42-3.29,4.93-7.74,9.19-17.88,14.03-29.66,14.07-13.35.05-26.71-1.15-40.06-1.82-.53-.03-1.05-.29-2.36-.68Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M165.06,132.92c5.07-5.07,9.55-9.66,14.19-14.08.75-.72,2.23-.95,3.36-.94,8.71.12,17.42.41,26.13.52,2.36.03,4.72-.41,7.08-.55,3.62-.22,4.97,1.64,3.43,4.97-2.32,5-6.35,8.45-11.49,9.94-4.49,1.3-9.29,2.12-13.95,2.08-8.8-.07-17.6-.9-26.39-1.43-.45-.03-.89-.19-2.36-.52Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M177.41,110.02c-.71-12.98-1.68-25.39,5.45-36.64,2.91-4.59,6.86-8.07,11.55-10.69.84-.47,2.08-.24,3.13-.34-.15,1.03.04,2.29-.49,3.06-6,8.7-7.54,18.22-5.58,28.48.15.8-.04,2.01-.56,2.55-4.26,4.42-8.64,8.73-13.5,13.59Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M113.43,123.38c.11,2.13.2,4.26.32,6.39.77,13.07,1.59,26.13,2.25,39.2.06,1.29-.59,2.9-1.44,3.91-2.06,2.41-4.44,4.55-7.17,7.28-.39-6.36-.88-12-1.04-17.65-.21-7.39-.48-14.81-.11-22.18.2-4.1,1.41-8.2,2.6-12.17.57-1.91,2.15-3.52,3.28-5.27l1.31.49Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M114.65,183.2c2.5-2.5,4.64-4.75,6.92-6.84.54-.49,1.57-.67,2.36-.62,14.21.84,28.41,1.73,42.61,2.64.81.05,1.6.37,3.13.74-1.31,1.31-2.03,2.61-3.07,2.97-4,1.37-8.11,3.48-12.15,3.43-12.79-.15-25.57-1.15-38.35-1.83-.27-.01-.53-.17-1.45-.49Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M188.32,109.66c3.06-3.06,6.08-6.15,9.21-9.13.4-.38,1.42-.34,2.08-.19,9.97,2.33,19.15.5,27.71-5.01,1.97-.91,2.03-.3,3.06-.43-.03,1.03.31,2.26-.13,3.07-3.33,6.01-7.89,10.79-14.85,12.29-8.8,1.9-17.69,1.09-26.54.35-.18-.32-.36-.64-.54-.96Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M67.14,180.11c-.99-6.48-1.09-13.83.72-20.63.29-1.09,1.44-2.72,2.23-2.74,1.28-.03,3.04.75,3.75,1.77.9,1.3,1.24,3.18,1.32,4.83.61,13.11,2.49,26.05,5.11,38.89.18.87.17,1.77.32,3.36-5.17-4.52-8.95-9.14-10.64-15.14" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M196.05,143.46c-5.62,5.61-11.85,7.13-18.41,6.99-8.8-.2-17.59-.94-26.39-1.47-.34-.02-.68-.2-1.84-.55,2.81-2.81,5.2-5.31,7.74-7.65.52-.48,1.59-.54,2.39-.49,10.88.63,21.75,1.28,32.63,2.01,1.17.08,2.31.67,3.89,1.16Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M104.14,224.04c-6.55-1.83-12.07-5.17-15.92-10.87,13.35,2.84,26.56,5.15,40.06,5.54,1.61.05,3.35-.33,4.79.18,1.4.5,3.05,1.64,3.6,2.92.79,1.85-.98,2.82-2.58,3.37-6.81,2.31-13.81,2.41-20.78,1.14" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
<path d="M67.24,220.69c2.21-2.21,4.38-4.46,6.64-6.62,2.14-2.04,4.64-2.39,6.06-.79,1.87,2.12.9,4.14-.71,5.8-4.54,4.69-9.14,9.34-13.83,13.89-1.6,1.55-3.67,2.31-5.54.39-1.83-1.88-1.09-3.93.42-5.58,2.23-2.44,4.66-4.71,7-7.06l-.04-.04Z" style="fill: #b6ade6; stroke-width: 0px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |