mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
Initial Leaf 1.19.3
This commit is contained in:
30
.github/workflows/ver1193.yml
vendored
Normal file
30
.github/workflows/ver1193.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Build Leaf 1.19.3
|
||||
on: [ push, pull_request ]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@master
|
||||
- name: Set up JDK
|
||||
uses: graalvm/setup-graalvm@v1
|
||||
with:
|
||||
version: "latest"
|
||||
java-version: 19
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
cache: gradle
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Configure Git
|
||||
run: git config --global user.email "no-reply@github.com" && git config --global user.name "Github Actions"
|
||||
- name: Apply patches
|
||||
run: ./gradlew -Dorg.gradle.jvmargs="-Dgraal.CompilerConfiguration=enterprise -Dgraal.UsePriorityInlining=true -Dgraal.Vectorization=true -Dgraal.OptDuplication=true --add-modules jdk.incubator.vector" applyPatches --stacktrace --no-daemon
|
||||
- name: Create ReobfPaperclipJar
|
||||
run: ./gradlew -Dorg.gradle.jvmargs="-Dgraal.CompilerConfiguration=enterprise -Dgraal.UsePriorityInlining=true -Dgraal.Vectorization=true -Dgraal.OptDuplication=true --add-modules jdk.incubator.vector" createReobfPaperclipJar --stacktrace --no-daemon
|
||||
- name: Rename Paperclip Jar
|
||||
run: mv build/libs/leaf-paperclip-1.19.3-R0.1-SNAPSHOT-reobf.jar ./leaf-1.19.3.jar
|
||||
- name: Upload Leaf
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Leaf
|
||||
path: ./leaf-1.19.3.jar
|
||||
63
.gitignore
vendored
63
.gitignore
vendored
@@ -1,14 +1,59 @@
|
||||
.gradle
|
||||
/build/
|
||||
# JVM crash related
|
||||
core.*
|
||||
hs_err_pid*
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
# Intellij
|
||||
.idea/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
out/
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
# Eclipse
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
# netbeans
|
||||
nbproject/
|
||||
nbactions.xml
|
||||
|
||||
# Gradle
|
||||
!gradle-wrapper.jar
|
||||
.gradle/
|
||||
build/
|
||||
*/build/
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
# we use maven!
|
||||
build.xml
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
# Maven
|
||||
log/
|
||||
target/
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
# various other potential build files
|
||||
build/
|
||||
bin/
|
||||
dist/
|
||||
manifest.mf
|
||||
|
||||
# Mac
|
||||
.DS_Store/
|
||||
.DS_Store
|
||||
|
||||
# vim
|
||||
.*.sw[a-p]
|
||||
|
||||
# Linux temp files
|
||||
*~
|
||||
|
||||
# other stuff
|
||||
run/
|
||||
|
||||
build-data/
|
||||
Leaf-API
|
||||
Leaf-MojangAPI
|
||||
Leaf-Server
|
||||
*.jar
|
||||
/patches/todo/
|
||||
449
CONTRIBUTING.md
Normal file
449
CONTRIBUTING.md
Normal file
@@ -0,0 +1,449 @@
|
||||
Contributing to Leaf
|
||||
==========================
|
||||
Leaf is happy you're willing to contribute to our projects. We are usually
|
||||
very lenient with all submitted PRs, but there are still some guidelines you
|
||||
can follow to make the approval process go more smoothly.
|
||||
|
||||
## Use a Personal Fork and not Organization
|
||||
|
||||
Leaf will routinely modify your PR, whether it's a quick rebase or to take care
|
||||
of any minor nitpicks we might have. Often, it's better for us to solve these
|
||||
problems for you than make you go back and forth trying to fix it yourself.
|
||||
|
||||
Unfortunately, if you use an organization for your PR, it prevents Leaf from
|
||||
modifying it. This requires us to manually merge your PR, resulting in us
|
||||
closing the PR instead of marking it as merged.
|
||||
|
||||
We much prefer to have PRs show as merged, so please do not use repositories
|
||||
on organizations for PRs.
|
||||
|
||||
See <https://github.com/isaacs/github/issues/1681> for more information on the
|
||||
issue.
|
||||
|
||||
## Requirements
|
||||
|
||||
To get started with PRing changes, you'll need the following software, most of
|
||||
which can be obtained in (most) package managers such as `apt` (Debian / Ubuntu;
|
||||
you will most likely use this for WSL), `homebrew` (macOS / Linux), and more:
|
||||
|
||||
- `git` (package `git` everywhere);
|
||||
- A Java 17 or later JDK (packages vary, use Google/DuckDuckGo/etc.).
|
||||
- [Adoptium](https://adoptium.net/) has builds for most operating systems.
|
||||
- Paper requires JDK 17 to build, however makes use of Gradle's
|
||||
[Toolchains](https://docs.gradle.org/current/userguide/toolchains.html)
|
||||
feature to allow building with only JRE 8 or later installed. (Gradle will
|
||||
automatically provision JDK 17 for compilation if it cannot find an existing
|
||||
install).
|
||||
|
||||
If you're on Windows, check
|
||||
[the section on WSL](#patching-and-building-is-really-slow-what-can-i-do).
|
||||
|
||||
If you're compiling with Docker, you can use Adoptium's
|
||||
[`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/) images like so:
|
||||
|
||||
```console
|
||||
# docker run -it -v "$(pwd)":/data --rm eclipse-temurin:17.0.1_12-jdk bash
|
||||
Pulling image...
|
||||
|
||||
root@abcdefg1234:/# javac -version
|
||||
javac 17.0.1
|
||||
```
|
||||
|
||||
## Understanding Patches
|
||||
|
||||
Leaf is mostly patches and extensions to Pufferfish. These patches/extensions are
|
||||
split into different directories which target certain parts of the code. These
|
||||
directories are:
|
||||
|
||||
- `Leaf-API` - Modifications to `Pufferfish-API`;
|
||||
- `Leaf-Server` - Modifications to `Pufferfish`.
|
||||
|
||||
Because the entire structure is based on patches and git, a basic understanding
|
||||
of how to use git is required. A basic tutorial can be found here:
|
||||
<https://git-scm.com/docs/gittutorial>.
|
||||
|
||||
Assuming you have already forked the repository:
|
||||
|
||||
1. Clone your fork to your local machine;
|
||||
2. Type `./gradlew applyPatches` in a terminal to apply the changes from upstream.
|
||||
On Windows, leave out the `./` at the beginning for all `gradlew` commands;
|
||||
3. cd into `Leaf-Server` for server changes, and `Leaf-API` for API changes.
|
||||
<!--You can also run `./paper server` or `./paper api` for these same directories
|
||||
respectively.
|
||||
1. You can also run `./paper setup`, which allows you to type `paper <command>`
|
||||
from anywhere in the Paper structure in most cases.-->
|
||||
|
||||
`Leaf-Server` and `Leaf-API` aren't git repositories in the traditional sense:
|
||||
|
||||
- `base` points to the unmodified source before Leaf patches have been applied.
|
||||
- Each commit after `base` is a patch.
|
||||
|
||||
## Adding Patches
|
||||
|
||||
Adding patches to Leaf is very simple:
|
||||
|
||||
1. Modify `Leaf-Server` and/or `Leaf-API` with the appropriate changes;
|
||||
1. Type `git add .` inside these directories to add your changes;
|
||||
1. Run `git commit` with the desired patch message;
|
||||
1. Run `./gradlew rebuildPatches` in the main directory to convert your commit into a new
|
||||
patch;
|
||||
1. PR the generated patch file(s) back to this repository.
|
||||
|
||||
Your commit will be converted into a patch that you can then PR into Leaf.
|
||||
|
||||
> ❗ Please note that if you have some specific implementation detail you'd like
|
||||
> to document, you should do so in the patch message *or* in comments.
|
||||
|
||||
## Modifying Patches
|
||||
|
||||
Modifying previous patches is a bit more complex:
|
||||
|
||||
### Method 1
|
||||
|
||||
This method works by temporarily resetting your `HEAD` to the desired commit to
|
||||
edit it using `git rebase`.
|
||||
|
||||
> ❗ While in the middle of an edit, you will not be able to compile unless you
|
||||
> *also* reset the opposing module(s) to a related commit. In the API's case,
|
||||
> you must reset the Server, and reset the API if you're editing the Server.
|
||||
> Note also that either module _may_ not compile when doing so. This is not
|
||||
> ideal nor intentional, but it happens. Feel free to fix this in a PR to us!
|
||||
|
||||
1. If you have changes you are working on, type `git stash` to store them for
|
||||
later;
|
||||
- You can type `git stash pop` to get them back at any point.
|
||||
1. Type `git rebase -i base`;
|
||||
- It should show something like
|
||||
[this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159) in
|
||||
the text editor you get.
|
||||
- If your editor does not have a "menu" at the bottom, you're using `vim`.
|
||||
If you don't know how to use `vim` and don't want to
|
||||
learn, enter `:q!` and press enter. Before redoing this step, do
|
||||
`export EDITOR=nano` for an easier editor to use.
|
||||
1. Replace `pick` with `edit` for the commit/patch you want to modify, and
|
||||
"save" the changes;
|
||||
- Only do this for **one** commit at a time.
|
||||
1. Make the changes you want to make to the patch;
|
||||
1. Type `git add .` to add your changes;
|
||||
1. Type `git commit --amend` to commit;
|
||||
- **Make sure to add `--amend`** or else a new patch will be created.
|
||||
- You can also modify the commit message and author here.
|
||||
1. Type `git rebase --continue` to finish rebasing;
|
||||
1. Type `./gradlew rebuildPatches` in the root directory;
|
||||
- This will modify the appropriate patches based on your commits.
|
||||
1. PR your modified patch file(s) back to this repository.
|
||||
|
||||
### Method 2 - Fixup commits
|
||||
|
||||
If you are simply editing a more recent commit or your change is small, simply
|
||||
making the change at HEAD and then moving the commit after you have tested it
|
||||
may be easier.
|
||||
|
||||
This method has the benefit of being able to compile to test your change without
|
||||
messing with your HEADs.
|
||||
|
||||
#### Manual method
|
||||
|
||||
1. Make your change while at HEAD;
|
||||
1. Make a temporary commit. You don't need to make a message for this;
|
||||
1. Type `git rebase -i base`, move (cut) your temporary commit and
|
||||
move it under the line of the patch you wish to modify;
|
||||
1. Change the `pick` to the appropriate action:
|
||||
1. `f`/`fixup`: Merge your changes into the patch without touching the
|
||||
message.
|
||||
1. `s`/`squash`: Merge your changes into the patch and use your commit message
|
||||
and subject.
|
||||
1. Type `./gradlew rebuildPatches` in the root directory;
|
||||
- This will modify the appropriate patches based on your commits.
|
||||
1. PR your modified patch file(s) back to this repository.
|
||||
|
||||
#### Automatic method
|
||||
|
||||
1. Make your change while at HEAD;
|
||||
1. Make a fixup commit. `git commit -a --fixup <hashOfPatchToFix>`;
|
||||
- You can also use `--squash` instead of `--fixup` if you want the commit
|
||||
message to also be changed.
|
||||
- You can get the hash by looking at `git log` or `git blame`; your IDE can
|
||||
assist you too.
|
||||
- Alternatively, if you only know the name of the patch, you can do
|
||||
`git commit -a --fixup "Subject of Patch name"`.
|
||||
1. Rebase with autosquash: `git rebase -i --autosquash base`.
|
||||
This will automatically move your fixup commit to the right place, and you just
|
||||
need to "save" the changes.
|
||||
1. Type `./gradlew rebuildPatches` in the root directory;
|
||||
- This will modify the appropriate patches based on your commits.
|
||||
1. PR your modified patch file(s) back to this repository.
|
||||
|
||||
## Rebasing PRs
|
||||
|
||||
Steps to rebase a PR to include the latest changes from `master`.
|
||||
These steps assume the `origin` remote is your fork of this repository and `upstream` is the official Leaf repository.
|
||||
|
||||
1. Pull the latest changes from upstreams master: `git checkout master && git pull upstream master`.
|
||||
1. Checkout feature/fix branch and rebase on master: `git checkout patch-branch && git rebase master`.
|
||||
1. Apply updated patches: `./gradlew applyPatches`.
|
||||
1. If there are conflicts, fix them.
|
||||
1. If your PR creates new patches instead of modifying exist ones, in both the `Leaf-Server` and `Leaf-API` directories, ensure your newly-created patch is the last commit by either:
|
||||
* Renaming the patch file with a large 4-digit number in front (e.g. 9999-Patch-to-add-some-new-stuff.patch), and re-applying patches.
|
||||
* Running `git rebase --interactive base` and moving the commits to the end.
|
||||
1. Rebuild patches: `./gradlew rebuildPatches`.
|
||||
1. Commit modified patches.
|
||||
1. Force push changes: `git push --force`.
|
||||
|
||||
## PR Policy
|
||||
|
||||
We'll accept changes that make sense. You should be able to justify their
|
||||
existence, along with any maintenance costs that come with them. Using
|
||||
[obfuscation helpers](#obfuscation-helpers) aids in the maintenance costs.
|
||||
Remember that these changes will affect everyone who runs Leaf, not just you
|
||||
and your server.
|
||||
|
||||
While we will fix minor formatting issues, you should stick to the guide below
|
||||
when making and submitting changes.
|
||||
|
||||
## Formatting
|
||||
|
||||
All modifications to non-Leaf files should be marked.
|
||||
|
||||
- Multi-line changes start with `// Leaf start` and end with `// Leaf end`;
|
||||
- You can put a comment with an explanation if it isn't obvious, like this:
|
||||
`// Leaf start - reason`.
|
||||
- The comments should generally be about the reason the change was made, what
|
||||
it was before, or what the change is.
|
||||
- Multi-line messages should start with `// Leaf start` and use `/* Multi
|
||||
line message here */` for the message itself.
|
||||
- One-line changes should have `// Leaf` or `// Leaf - reason`.
|
||||
|
||||
Here's an example of how to mark changes by Leaf:
|
||||
|
||||
```java
|
||||
entity.getWorld().dontbeStupid(); // Leaf - was beStupid() which is bad
|
||||
entity.getFriends().forEach(Entity::explode);
|
||||
entity.a();
|
||||
entity.b();
|
||||
// Leaf start - use plugin-set spawn
|
||||
// entity.getWorld().explode(entity.getWorld().getSpawn());
|
||||
Location spawnLocation = ((CraftWorld)entity.getWorld()).getSpawnLocation();
|
||||
entity.getWorld().explode(new BlockPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ()));
|
||||
// Leaf end
|
||||
```
|
||||
|
||||
We generally follow usual Java style (aka. Oracle style), or what is programmed
|
||||
into most IDEs and formatters by default. There are a few notes, however:
|
||||
- It is fine to go over 80 lines as long as it doesn't hurt readability.
|
||||
There are exceptions, especially in Spigot-related files
|
||||
- When in doubt or the code around your change is in a clearly different style,
|
||||
use the same style as the surrounding code.
|
||||
|
||||
## Patch Notes
|
||||
|
||||
When submitting patches to Leaf, we may ask you to add notes to the patch
|
||||
header. While we do not require it for all changes, you should add patch notes
|
||||
when the changes you're making are technical, complex, or require an explanation
|
||||
of some kind. It is very likely that your patch will remain long after we've all
|
||||
forgotten about the details of your PR; patch notes will help us maintain it
|
||||
without having to dig back through GitHub history looking for your PR.
|
||||
|
||||
These notes should express the intent of your patch, as well as any pertinent
|
||||
technical details we should keep in mind long-term. Ultimately, they exist to
|
||||
make it easier for us to maintain the patch across major version changes.
|
||||
|
||||
If you add a message to your commit in the `Leaf-Server`/`Leaf-API`
|
||||
directories, the rebuild patches script will handle these patch notes
|
||||
automatically as part of generating the patch file. If you are not
|
||||
extremely careful, you should always just `squash` or `amend` a patch (see the
|
||||
above sections on modifying patches) and rebuild.
|
||||
|
||||
Editing messages and patches by hand is possible, but you should patch and
|
||||
rebuild afterwards to make sure you did it correctly. This is slower than just
|
||||
modifying the patches properly after a few times, so you will not really gain
|
||||
anything but headaches from doing it by hand.
|
||||
|
||||
Underneath is an example patch header/note:
|
||||
|
||||
```patch
|
||||
From 02abc033533f70ef3165a97bfda3f5c2fa58633a Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 15 Oct 2017 00:29:07 +0100
|
||||
Subject: [PATCH] revert serverside behavior of keepalives
|
||||
|
||||
This patch intends to bump up the time that a client has to reply to the
|
||||
server back to 30 seconds as per pre 1.12.2, which allowed clients
|
||||
more than enough time to reply potentially allowing them to be less
|
||||
tempermental due to lag spikes on the network thread, e.g. that caused
|
||||
by plugins that are interacting with netty.
|
||||
|
||||
We also add a system property to allow people to tweak how long the server
|
||||
will wait for a reply. There is a compromise here between lower and higher
|
||||
values, lower values will mean that dead connections can be closed sooner,
|
||||
whereas higher values will make this less sensitive to issues such as spikes
|
||||
from networking or during connections flood of chunk packets on slower clients,
|
||||
at the cost of dead connections being kept open for longer.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
index a92bf8967..d0ab87d0f 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
```
|
||||
|
||||
## Obfuscation Helpers
|
||||
|
||||
While rarely needed, obfuscation helpers are sometimes useful when it comes
|
||||
to unmapped local variables, or poorly named method parameters. In an effort
|
||||
to make future updates easier on ourselves, Leaf tries to use obfuscation
|
||||
helpers wherever it makes sense. The purpose of these helpers is to make the
|
||||
code more readable and maintainable. These helpers should be made easy to
|
||||
inline by the JVM wherever possible.
|
||||
|
||||
An example of an obfuscation helper for a local variable:
|
||||
```java
|
||||
double d0 = entity.getX(); final double fromX = d0; // Leaf - OBFHELPER
|
||||
// ...
|
||||
this.someMethod(fromX); // Leaf
|
||||
```
|
||||
|
||||
While they may not always be done in exactly the same way, the general goal is
|
||||
always to improve readability and maintainability. Use your best judgment and do
|
||||
what fits best in your situation.
|
||||
|
||||
## Configuration files
|
||||
|
||||
To use a configurable value in your patch, add a new field in either the
|
||||
`GlobalConfiguration` or `WorldConfiguration` classes (inside the
|
||||
`io.papermc.paper.configuration` package). Use `GlobalConfiguration` if a value
|
||||
must remain the same throughout all worlds, or the latter if it can change
|
||||
between worlds. World-specific configuration options are preferred whenever
|
||||
possible.
|
||||
|
||||
### Example
|
||||
This is adding a new miscellaneous setting that doesn't seem to fit in other categories.
|
||||
Try to check and see if an existing category (inner class) exists that matches
|
||||
whatever configuration option you are adding.
|
||||
```java
|
||||
public class GlobalConfiguration {
|
||||
// other sections
|
||||
public class Misc extends ConfigurationPart {
|
||||
// other settings
|
||||
public boolean lagCompensateBlockBreaking = true;
|
||||
public boolean useDimensionTypeForCustomSpawners = false;
|
||||
public int maxNumOfPlayers = 20; // This is the new setting
|
||||
}
|
||||
}
|
||||
```
|
||||
You set the type of the setting as the field type, and the default value is the
|
||||
initial field value. The name of the setting defaults to the snake-case of the
|
||||
field name, so in this case it would be `misc.max-num-of-players`. You can use
|
||||
the `@Setting` annotation to override that, but generally just try to set the
|
||||
field name to what you want the setting to be called.
|
||||
|
||||
#### Accessing the value
|
||||
If you added a new global config value, you can access it in the code just by
|
||||
doing
|
||||
```java
|
||||
int maxPlayers = GlobalConfiguration.get().misc.maxNumOfPlayers;
|
||||
```
|
||||
Generally for global config values you will use the fully qualified class name,
|
||||
`io.papermc.paper.configuration.GlobalConfiguration` since it's not imported in
|
||||
most places.
|
||||
---
|
||||
If you are adding a new world config value, you must have access to an instance
|
||||
of the `net.minecraft.world.level.Level` which you can then access the config by doing
|
||||
```java
|
||||
int maxPlayers = level.paperConfig().misc.maxNumOfPlayers;
|
||||
```
|
||||
|
||||
#### Committing changes
|
||||
All changes to the `GlobalConfiguration` and `WorldConfiguration` files
|
||||
should be done in the commit that created them. So do an interactive rebase
|
||||
or fixup to apply just those changes to that commit, then add a new commit
|
||||
that includes the logic that uses that option in the server somewhere.
|
||||
|
||||
## Testing API changes
|
||||
|
||||
### Using the Leaf Test Plugin
|
||||
|
||||
The Leaf project has a `test-plugin` module for easily testing out API changes
|
||||
and additions. To use the test plugin, enable it in `test-plugin.settings.gradle.kts`,
|
||||
which will be generated after running Gradle at least once. After this, you can edit
|
||||
the test plugin, and run a server with the plugin using `./gradlew runDev` (or any
|
||||
of the other Leaf run tasks).
|
||||
|
||||
### Publishing to Maven local (use in external plugins)
|
||||
|
||||
To build and install the Leaf APIs and Server to your local Maven repository, do the following:
|
||||
|
||||
- Run `./gradlew publishToMavenLocal` in the base directory.
|
||||
|
||||
If you use Gradle to build your plugin:
|
||||
- Add `mavenLocal()` as a repository. Gradle checks repositories in the order they are declared,
|
||||
so if you also have the Leaf repository added, put the local repository above Leaf's.
|
||||
- Make sure to remove `mavenLocal()` when you are done testing, see the [Gradle docs](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:case-for-maven-local)
|
||||
for more details.
|
||||
|
||||
If you use Maven to build your plugin:
|
||||
- If you later need to use the Leaf-API, you might want to remove the jar
|
||||
from your local Maven repository.
|
||||
If you use Windows and don't usually build using WSL, you might not need to
|
||||
do this.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### I can't find the NMS file I need!
|
||||
|
||||
By default, Leaf (and upstream) only import files we make changes to. If you
|
||||
would like to make changes to a file that isn't present in `Leaf-Server`'s
|
||||
source directory, you just need to add it to our import script ran during the
|
||||
patching process.
|
||||
|
||||
1. Save (rebuild) any patches you are in the middle of working on! Their
|
||||
progress will be lost if you do not;
|
||||
1. Identify the name(s) of the file(s) you want to import.
|
||||
- A complete list of all possible file names can be found at
|
||||
`./Leaf-Server/.gradle/caches/paperweight/mc-dev-sources/net/minecraft/`. You might find
|
||||
[MappingViewer] useful if you need to translate between Mojang and Spigot mapped names.
|
||||
1. Open the file at `./build-data/dev-imports.txt` and add the name of your file to
|
||||
the script. Follow the instructions there;
|
||||
1. Re-patch the server `./gradlew applyPatches`;
|
||||
1. Edit away!
|
||||
|
||||
> ❗ This change is temporary! **DO NOT COMMIT CHANGES TO THIS FILE!**
|
||||
> Once you have made your changes to the new file, and rebuilt patches, you may
|
||||
> undo your changes to `dev-imports.txt`.
|
||||
|
||||
Any file modified in a patch file gets automatically imported, so you only need
|
||||
this temporarily to import it to create the first patch.
|
||||
|
||||
To undo your changes to the file, type `git checkout build-data/dev-imports.txt`.
|
||||
|
||||
### My commit doesn't need a build, what do I do?
|
||||
|
||||
Well, quite simple: You add `[ci skip]` to the start of your commit subject.
|
||||
|
||||
This case most often applies to changes to files like `README.md`, this very
|
||||
file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth.
|
||||
|
||||
### Patching and building is *really* slow, what can I do?
|
||||
|
||||
This only applies if you're running Windows. If you're running a prior Windows
|
||||
release, either update to Windows 10/11 or move to macOS/Linux/BSD.
|
||||
|
||||
In order to speed up patching process on Windows, it's recommended you get WSL
|
||||
2. This is available in Windows 10 v2004, build 19041 or higher. (You can check
|
||||
your version by running `winver` in the run window (Windows key + R)). If you're
|
||||
using an out of date version of Windows 10, update your system with the
|
||||
[Windows 10 Update Assistant](https://www.microsoft.com/en-us/software-download/windows10) or [Windows 11 Update Assistant](https://www.microsoft.com/en-us/software-download/windows11).
|
||||
|
||||
To set up WSL 2, follow the information here:
|
||||
<https://docs.microsoft.com/en-us/windows/wsl/install>
|
||||
|
||||
You will most likely want to use the Ubuntu apps. Once it's set up, install the
|
||||
required tools with `sudo apt-get update && sudo apt-get install $TOOL_NAMES
|
||||
-y`. Replace `$TOOL_NAMES` with the packages found in the
|
||||
[requirements](#requirements). You can now clone the repository and do
|
||||
everything like usual.
|
||||
|
||||
> ❗ Do not use the `/mnt/` directory in WSL! Instead, mount the WSL directories
|
||||
> in Windows like described here:
|
||||
> <https://docs.microsoft.com/en-us/windows/wsl/filesystems#view-your-current-directory-in-windows-file-explorer>
|
||||
|
||||
[MappingViewer]: https://nms.screamingsandals.org/
|
||||
23
LICENSE
Normal file
23
LICENSE
Normal file
@@ -0,0 +1,23 @@
|
||||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the “Software”), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, 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.
|
||||
60
README.md
60
README.md
@@ -1,2 +1,58 @@
|
||||
# Leaf
|
||||
Personal fork of Purpur, A Minecraft Server Software for Winds Network
|
||||
<img src="Leaf.png" alt="Leaf logo" align="right" width="400">
|
||||
<div align="center">
|
||||
|
||||
## Leaf
|
||||
|
||||
[](https://github.com/Winds-Studio/Leaf/actions)
|
||||
[](LICENSE)
|
||||
|
||||
<h5>Leaf is a drop-in replacement for <a href="https://github.com/pufferfish-gg/Pufferfish">Pufferfish</a> servers designed for fix some bugs and customize, and performance built on top of <a href="https://github.com/pufferfish-gg/Pufferfish">Pufferfish</a>.</h5>
|
||||
<h8>Logo created by <a href="https://github.com/naiximcn">NaixiNana</a></h8>
|
||||
</div>
|
||||
|
||||
## Features
|
||||
- Fork of [Pufferfish](https://github.com/pufferfish-gg/Pufferfish) for better performance.
|
||||
- Allowing all characters as username, including Chinese and other characters.
|
||||
- Allowing players connect to backend server through proxy without enabling bunngecord mode.
|
||||
- Allowing players use tripwire dupe.
|
||||
- Disabling the UseItemOnPacket Too Far check.
|
||||
- Update all dependencies to the latest.
|
||||
- Some Purpur patches.
|
||||
- ...
|
||||
|
||||
## Contact
|
||||
|
||||
- 📫 Discord: `Dreeam#0851` | QQ: `2682173972`
|
||||
|
||||
|
||||
## Downloads
|
||||
|
||||
Downloads can be obtained in the [Actions](https://github.com/Dreeam-qwq/Leaf/actions) or [Releases](https://github.com/Dreeam-qwq/Leaf/releases)
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
Building a Paperclip JAR for distribution:
|
||||
|
||||
```bash
|
||||
./gradlew applyPatches && ./gradlew createReobfPaperclipJar
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
[](LICENSE)
|
||||
|
||||
All patches are licensed under the MIT license, unless otherwise noted in the patch headers.
|
||||
|
||||
See [PaperMC/Paper](https://github.com/PaperMC/Paper), and [PaperMC/Paperweight](https://github.com/PaperMC/paperweight) for the license of material used by this project.
|
||||
|
||||
Yes, this also includes all API provided by Paper, Spigot, and Bukkit.
|
||||
|
||||
|
||||
Credits:
|
||||
-------------
|
||||
|
||||
- [Pufferfish](https://github.com/pufferfish-gg/Pufferfish)
|
||||
- [Gale](https://github.com/GaleMC/Gale)
|
||||
- [Purpur](https://github.com/PurpurMC/Purpur)
|
||||
- [KeYi](https://github.com/KeYiMC/KeYi)
|
||||
80
build.gradle.kts
Normal file
80
build.gradle.kts
Normal file
@@ -0,0 +1,80 @@
|
||||
import io.papermc.paperweight.util.constants.*
|
||||
|
||||
plugins {
|
||||
java
|
||||
`maven-publish`
|
||||
id("com.github.johnrengelman.shadow") version "7.1.2" apply false
|
||||
id("io.papermc.paperweight.patcher") version "1.4.0"
|
||||
}
|
||||
|
||||
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven(paperMavenPublicUrl) {
|
||||
content { onlyForConfigurations(configurations.paperclip.name) }
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
remapper("net.fabricmc:tiny-remapper:0.8.6:fat")
|
||||
decompiler("org.quiltmc:quiltflower:1.9.0")
|
||||
paperclip("io.papermc:paperclip:3.0.3-SNAPSHOT")
|
||||
}
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "java")
|
||||
apply(plugin = "maven-publish")
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
tasks.withType<Javadoc> {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
tasks.withType<ProcessResources> {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven(paperMavenPublicUrl)
|
||||
maven("https://oss.sonatype.org/content/groups/public/")
|
||||
maven("https://ci.emc.gs/nexus/content/groups/aikar/")
|
||||
maven("https://repo.aikar.co/content/groups/aikar")
|
||||
maven("https://repo.md-5.net/content/repositories/releases/")
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
maven("https://jitpack.io")
|
||||
maven("https://repo.codemc.io/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
|
||||
paperweight {
|
||||
serverProject.set(project(":leaf-server"))
|
||||
|
||||
remapRepo.set("https://maven.fabricmc.net/")
|
||||
decompileRepo.set("https://maven.quiltmc.org/")
|
||||
|
||||
useStandardUpstream("Pufferfish") {
|
||||
url.set(github("pufferfish-gg", "Pufferfish"))
|
||||
ref.set(providers.gradleProperty("PufferfishCommit"))
|
||||
|
||||
withStandardPatcher {
|
||||
apiSourceDirPath.set("pufferfish-api")
|
||||
serverSourceDirPath.set("pufferfish-server")
|
||||
|
||||
apiPatchDir.set(layout.projectDirectory.dir("patches/api"))
|
||||
apiOutputDir.set(layout.projectDirectory.dir("Leaf-API"))
|
||||
|
||||
serverPatchDir.set(layout.projectDirectory.dir("patches/server"))
|
||||
serverOutputDir.set(layout.projectDirectory.dir("Leaf-Server"))
|
||||
}
|
||||
}
|
||||
}
|
||||
9
gradle.properties
Normal file
9
gradle.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
group = org.dreeam.leaf
|
||||
version = 1.19.3-R0.1-SNAPSHOT
|
||||
|
||||
PufferfishCommit = 9771bd7e692b5f4133e5846123c2f3a9c315e75f
|
||||
|
||||
org.gradle.caching = true
|
||||
org.gradle.parallel = true
|
||||
org.gradle.vfs.watch = false
|
||||
org.gradle.jvmargs = -Xmx3G
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
244
gradlew
vendored
Normal file
244
gradlew
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
92
gradlew.bat
vendored
Normal file
92
gradlew.bat
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
25
patches/api/0001-Leaf-config-files.patch
Normal file
25
patches/api/0001-Leaf-config-files.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Thu, 11 Aug 2022 04:13:27 +0800
|
||||
Subject: [PATCH] Leaf config files
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 2204336d8800311b65e894739ab1b27273e7c6f2..39808c0cc23a97f707366378f28ba64b80e6acbb 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -1971,6 +1971,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Leaf start
|
||||
+ @NotNull
|
||||
+ public org.bukkit.configuration.file.YamlConfiguration getLeafConfig()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException("Not supported yet.");
|
||||
+ }
|
||||
+ // Leaf end
|
||||
+
|
||||
/**
|
||||
* Sends the component to the player
|
||||
*
|
||||
74
patches/api/0002-Bump-Dependencies.patch
Normal file
74
patches/api/0002-Bump-Dependencies.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Fri, 28 Oct 2022 17:24:16 -0400
|
||||
Subject: [PATCH] Bump Dependencies
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index a995ecc3b1d6181c58d5b4a0a6a893178bdc40aa..63f4b9697415f073937ae08bafb6b8b0b85f174d 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -25,13 +25,13 @@ dependencies {
|
||||
// api dependencies are listed transitively to API consumers
|
||||
api("com.google.guava:guava:31.1-jre")
|
||||
api("com.google.code.gson:gson:2.10")
|
||||
- api("net.md-5:bungeecord-chat:1.16-R0.4-deprecated+build.6") // Paper
|
||||
+ api("net.md-5:bungeecord-chat:1.19-R0.1-SNAPSHOT") // Paper
|
||||
api("org.yaml:snakeyaml:1.33")
|
||||
// Paper start
|
||||
api("com.googlecode.json-simple:json-simple:1.1.1") {
|
||||
isTransitive = false // includes junit
|
||||
}
|
||||
- api("it.unimi.dsi:fastutil:8.5.6")
|
||||
+ api("it.unimi.dsi:fastutil:8.5.11")
|
||||
apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
|
||||
apiAndDocs("net.kyori:adventure-api")
|
||||
apiAndDocs("net.kyori:adventure-text-minimessage")
|
||||
@@ -39,18 +39,18 @@ dependencies {
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
|
||||
apiAndDocs("net.kyori:adventure-text-serializer-plain")
|
||||
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
|
||||
- api("org.apache.logging.log4j:log4j-api:2.17.1")
|
||||
- api("org.slf4j:slf4j-api:1.8.0-beta4")
|
||||
- api("io.sentry:sentry:5.4.0") // Pufferfish
|
||||
+ api("org.apache.logging.log4j:log4j-api:2.19.0")
|
||||
+ api("org.slf4j:slf4j-api:1.8.0-beta4") // Leaf TODO - Bump later, need to fix breaking compatibility
|
||||
+ api("io.sentry:sentry:6.10.0") // Pufferfish
|
||||
|
||||
- implementation("org.ow2.asm:asm:9.2")
|
||||
- implementation("org.ow2.asm:asm-commons:9.2")
|
||||
+ implementation("org.ow2.asm:asm:9.4")
|
||||
+ implementation("org.ow2.asm:asm-commons:9.4")
|
||||
// Paper end
|
||||
|
||||
compileOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
||||
- compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
|
||||
- compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3")
|
||||
- compileOnly("com.google.code.findbugs:jsr305:1.3.9") // Paper
|
||||
+ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.2")
|
||||
+ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.2")
|
||||
+ compileOnly("com.google.code.findbugs:jsr305:3.0.2") // Paper
|
||||
|
||||
val annotations = "org.jetbrains:annotations:23.0.0" // Paper - we don't want Java 5 annotations...
|
||||
compileOnly(annotations)
|
||||
@@ -64,8 +64,8 @@ dependencies {
|
||||
|
||||
testImplementation("org.apache.commons:commons-lang3:3.12.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
- testImplementation("org.hamcrest:hamcrest-library:1.3")
|
||||
- testImplementation("org.ow2.asm:asm-tree:9.3")
|
||||
+ testImplementation("org.hamcrest:hamcrest-library:2.2")
|
||||
+ testImplementation("org.ow2.asm:asm-tree:9.4")
|
||||
}
|
||||
|
||||
configure<PublishingExtension> {
|
||||
@@ -147,6 +147,9 @@ val scanJar = tasks.register("scanJarForBadCalls", io.papermc.paperweight.tasks.
|
||||
jarToScan.set(tasks.jar.flatMap { it.archiveFile })
|
||||
classpath.from(configurations.compileClasspath)
|
||||
}
|
||||
+repositories {
|
||||
+ mavenCentral()
|
||||
+}
|
||||
tasks.check {
|
||||
dependsOn(scanJar)
|
||||
}
|
||||
46
patches/api/0003-Purpur-Lagging-threshold.patch
Normal file
46
patches/api/0003-Purpur-Lagging-threshold.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Tue, 23 Jul 2019 10:07:24 -0500
|
||||
Subject: [PATCH] Purpur: Lagging threshold
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index ac9b690fcccb60b587e5345f12f1383afd0a73a1..0a4320b32485db84a0be16535b406f043e3177a2 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -2464,4 +2464,15 @@ public final class Bukkit {
|
||||
public static Server.Spigot spigot() {
|
||||
return server.spigot();
|
||||
}
|
||||
+
|
||||
+ // Purpur start
|
||||
+ /**
|
||||
+ * Check if server is lagging according to laggy threshold setting
|
||||
+ *
|
||||
+ * @return True if lagging
|
||||
+ */
|
||||
+ public static boolean isLagging() {
|
||||
+ return server.isLagging();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 39808c0cc23a97f707366378f28ba64b80e6acbb..8eb8a788dc3dbc0d5ac24089a57c730089fd8dbe 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2147,4 +2147,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
@NotNull org.bukkit.potion.PotionBrewer getPotionBrewer();
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start
|
||||
+ /**
|
||||
+ * Check if server is lagging according to laggy threshold setting
|
||||
+ *
|
||||
+ * @return True if lagging
|
||||
+ */
|
||||
+ boolean isLagging();
|
||||
+ // Purpur end
|
||||
}
|
||||
98
patches/api/0004-Purpur-ChatColor-conveniences.patch
Normal file
98
patches/api/0004-Purpur-ChatColor-conveniences.patch
Normal file
@@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 10 Jul 2020 12:43:25 -0500
|
||||
Subject: [PATCH] Purpur: ChatColor conveniences
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/ChatColor.java b/src/main/java/org/bukkit/ChatColor.java
|
||||
index f6eb30f53dad684f156102cf7147b2f00c82c71e..f1239a2618b08fa92e0e20692d1c3d20d1558502 100644
|
||||
--- a/src/main/java/org/bukkit/ChatColor.java
|
||||
+++ b/src/main/java/org/bukkit/ChatColor.java
|
||||
@@ -3,6 +3,7 @@ package org.bukkit;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Map;
|
||||
+import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -413,4 +414,77 @@ public enum ChatColor {
|
||||
BY_CHAR.put(color.code, color);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Purpur start
|
||||
+ /**
|
||||
+ * Convert legacy string into a string ready to be parsed by MiniMessage
|
||||
+ *
|
||||
+ * @param str Legacy string
|
||||
+ * @return MiniMessage ready string
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public static String toMM(@NotNull String str) {
|
||||
+ StringBuilder sb = new StringBuilder(str);
|
||||
+ Matcher m = STRIP_COLOR_PATTERN.matcher(sb);
|
||||
+ while (m.find()) {
|
||||
+ sb.replace(m.start(), m.end(), sb.substring(m.start(), m.end()).toLowerCase());
|
||||
+ }
|
||||
+ return sb.toString()
|
||||
+ .replace("&0", "<black>")
|
||||
+ .replace("&1", "<dark_blue>")
|
||||
+ .replace("&2", "<dark_green>")
|
||||
+ .replace("&3", "<dark_aqua>")
|
||||
+ .replace("&4", "<dark_red>")
|
||||
+ .replace("&5", "<dark_purple>")
|
||||
+ .replace("&6", "<gold>")
|
||||
+ .replace("&7", "<grey>")
|
||||
+ .replace("&8", "<dark_grey>")
|
||||
+ .replace("&9", "<blue>")
|
||||
+ .replace("&a", "<green>")
|
||||
+ .replace("&b", "<aqua>")
|
||||
+ .replace("&c", "<red>")
|
||||
+ .replace("&d", "<light_purple>")
|
||||
+ .replace("&e", "<yellow>")
|
||||
+ .replace("&f", "<white>")
|
||||
+ .replace("&k", "<obf>")
|
||||
+ .replace("&l", "<b>")
|
||||
+ .replace("&m", "<st>")
|
||||
+ .replace("&n", "<u>")
|
||||
+ .replace("&o", "<i>")
|
||||
+ .replace("&r", "<r>");
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static net.kyori.adventure.text.Component parseMM(@NotNull String string, @Nullable Object... args) {
|
||||
+ return net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(String.format(string, args));
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ public static final Pattern HEX_PATTERN = Pattern.compile("(#[A-Fa-f0-9]{6})");
|
||||
+
|
||||
+ @Deprecated
|
||||
+ @Nullable
|
||||
+ public static String replaceHex(@Nullable String str) {
|
||||
+ if (str != null) {
|
||||
+ java.util.regex.Matcher matcher = HEX_PATTERN.matcher(str);
|
||||
+ while (matcher.find()) {
|
||||
+ String group = matcher.group(1);
|
||||
+ str = str.replace(group, net.md_5.bungee.api.ChatColor.of(group).toString());
|
||||
+ }
|
||||
+ }
|
||||
+ return str;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ @Nullable
|
||||
+ public static String color(@Nullable String str) {
|
||||
+ return color(str, true);
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated
|
||||
+ @Nullable
|
||||
+ public static String color(@Nullable String str, boolean parseHex) {
|
||||
+ return str != null ? net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', parseHex ? replaceHex(str) : str) : str;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Parker Hawke <hawkeboyz2@hotmail.com>
|
||||
Date: Sat, 27 Jun 2020 18:43:37 -0400
|
||||
Subject: [PATCH] Purpur: Spigot - Improve output of plugins command
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
Co-authored-by: Oharass <oharass@bk.ru>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
index 1aa58c59e1e8738bbdc77752885ff3b18b29de42..46525191653e4ac0e0366c0357f368c0b709f20d 100644
|
||||
--- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
+++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java
|
||||
@@ -11,6 +11,14 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
+// Spigot start
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.TextComponent;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.plugin.PluginDescriptionFile;
|
||||
+// Spigot end
|
||||
|
||||
public class PluginsCommand extends BukkitCommand {
|
||||
public PluginsCommand(@NotNull String name) {
|
||||
@@ -25,7 +33,13 @@ public class PluginsCommand extends BukkitCommand {
|
||||
public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
|
||||
if (!testPermission(sender)) return true;
|
||||
|
||||
- sender.sendMessage("Plugins " + getPluginList());
|
||||
+ // Spigot start
|
||||
+ if (sender instanceof Player && sender.hasPermission("bukkit.command.version")) {
|
||||
+ sender.sendMessage(getPluginListSpigot());
|
||||
+ } else {
|
||||
+ sender.sendMessage("Plugins " + getPluginList());
|
||||
+ }
|
||||
+ // Spigot end
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -71,4 +85,73 @@ public class PluginsCommand extends BukkitCommand {
|
||||
// Paper end
|
||||
}
|
||||
|
||||
+ // Spigot start
|
||||
+ @NotNull
|
||||
+ private TextComponent getPluginListSpigot() {
|
||||
+ Plugin[] plugins = Bukkit.getPluginManager().getPlugins();
|
||||
+ TextComponent.Builder builder = Component.text();
|
||||
+ builder.append(Component.text("Plugins (" + plugins.length + "): "));
|
||||
+
|
||||
+ int index = 0;
|
||||
+ for (Plugin plugin : plugins) {
|
||||
+ if (index++ > 0) {
|
||||
+ builder.append(Component.text(", ", NamedTextColor.WHITE));
|
||||
+ }
|
||||
+
|
||||
+ // Event components
|
||||
+ PluginDescriptionFile description = plugin.getDescription();
|
||||
+ TextComponent.Builder hover = Component.text();
|
||||
+ hover.append(Component.text("Version: ", NamedTextColor.WHITE)).append(Component.text(description.getVersion(), NamedTextColor.GREEN));
|
||||
+
|
||||
+ if (description.getDescription() != null) {
|
||||
+ hover.append(Component.newline())
|
||||
+ .append(Component.text("Description: ", NamedTextColor.WHITE))
|
||||
+ .append(Component.text(description.getDescription(), NamedTextColor.GREEN));
|
||||
+ }
|
||||
+
|
||||
+ if (description.getWebsite() != null) {
|
||||
+ hover.append(Component.newline())
|
||||
+ .append(Component.text("Website: ", NamedTextColor.WHITE))
|
||||
+ .append(Component.text(description.getWebsite(), NamedTextColor.GREEN));
|
||||
+ }
|
||||
+
|
||||
+ if (!description.getAuthors().isEmpty()) {
|
||||
+ hover.append(Component.newline());
|
||||
+ if (description.getAuthors().size() == 1) {
|
||||
+ hover.append(Component.text("Author: "));
|
||||
+ } else {
|
||||
+ hover.append(Component.text("Authors: "));
|
||||
+ }
|
||||
+
|
||||
+ hover.append(getAuthors(description));
|
||||
+ }
|
||||
+
|
||||
+ // Plugin list entry
|
||||
+ builder.append(Component.text(plugin.getDescription().getName(), plugin.isEnabled() ? NamedTextColor.GREEN : NamedTextColor.RED)
|
||||
+ .hoverEvent(hover.build()).clickEvent(ClickEvent.suggestCommand("/version " + description.getName())));
|
||||
+
|
||||
+ if (plugin.getDescription().getProvides().size() > 0) {
|
||||
+ builder.append(Component.text(" (", NamedTextColor.WHITE)).append(Component.text(String.join(", ", plugin.getDescription().getProvides()))).append(Component.text(")"));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return builder.build();
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ private TextComponent getAuthors(@NotNull final PluginDescriptionFile description) {
|
||||
+ TextComponent.Builder builder = Component.text();
|
||||
+ List<String> authors = description.getAuthors();
|
||||
+
|
||||
+ for (int i = 0; i < authors.size(); i++) {
|
||||
+ if (i > 0) {
|
||||
+ builder.append(Component.text(i < authors.size() - 1 ? ", " : " and ", NamedTextColor.WHITE));
|
||||
+ }
|
||||
+
|
||||
+ builder.append(Component.text(authors.get(i), NamedTextColor.GREEN));
|
||||
+ }
|
||||
+
|
||||
+ return builder.build();
|
||||
+ }
|
||||
+ // Spigot end
|
||||
}
|
||||
27
patches/api/0006-Purpur-Lobotomize-stuck-villagers.patch
Normal file
27
patches/api/0006-Purpur-Lobotomize-stuck-villagers.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
|
||||
Date: Mon, 24 Jan 2022 20:42:22 -0600
|
||||
Subject: [PATCH] Purpur: Lobotomize stuck villagers
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java
|
||||
index c61e7e41aeb3d4f5f4ac47da8890051d8e97340d..12b08318f78c8144cc809dbccf0feabdd31f0ee2 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Villager.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Villager.java
|
||||
@@ -328,4 +328,14 @@ public interface Villager extends AbstractVillager {
|
||||
*/
|
||||
public void clearReputations();
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start
|
||||
+
|
||||
+ /**
|
||||
+ * Check if villager is currently lobotomized
|
||||
+ *
|
||||
+ * @return True if lobotomized
|
||||
+ */
|
||||
+ boolean isLobotomized();
|
||||
+ // Purpur end
|
||||
}
|
||||
50
patches/api/0007-KeYi-Optimize-Spigot-event-bus.patch
Normal file
50
patches/api/0007-KeYi-Optimize-Spigot-event-bus.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <lynxplay101@gmail.com>
|
||||
Date: Thu, 9 Dec 2021 01:53:30 +0100
|
||||
Subject: [PATCH] KeYi: Optimize Spigot event bus
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original code by lynxplay, licensed under GNU General Public License v3.0
|
||||
You can find the original code on https://github.com/lynxplay/ktp
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/plugin/RegisteredListener.java b/src/main/java/org/bukkit/plugin/RegisteredListener.java
|
||||
index 3b3d9642a8d63798dc28f2f8df77f0466451cbff..8d3605f25e97a375971705c737bc7bacbac045cd 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/RegisteredListener.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/RegisteredListener.java
|
||||
@@ -62,8 +62,10 @@ public class RegisteredListener {
|
||||
* @throws EventException If an event handler throws an exception.
|
||||
*/
|
||||
public void callEvent(@NotNull final Event event) throws EventException {
|
||||
- if (event instanceof Cancellable) {
|
||||
- if (((Cancellable) event).isCancelled() && isIgnoringCancelled()) {
|
||||
+ // KTP start - optimize spigot event bus
|
||||
+ if (isIgnoringCancelled()) {
|
||||
+ if (event instanceof Cancellable cancellable && cancellable.isCancelled()) {
|
||||
+ // KTP end - optimize spigot event bus
|
||||
return;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
index c077e7c883613fcb6e559b4e4776e794caa3b363..ba869354adc59db2fc547c481c1ed4d5d0af23b7 100644
|
||||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -656,11 +656,15 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
public void callEvent(@NotNull Event event) {
|
||||
// Paper - replace callEvent by merging to below method
|
||||
- if (event.isAsynchronous() && server.isPrimaryThread()) {
|
||||
+ // KTP start - optimize spigot event bus
|
||||
+ final boolean isAsync = event.isAsynchronous();
|
||||
+ final boolean isPrimary = server.isPrimaryThread(); // Cache to prevent multiple thread object comparisons.
|
||||
+ if (isAsync && isPrimary) {
|
||||
throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously.");
|
||||
- } else if (!event.isAsynchronous() && !server.isPrimaryThread() && !server.isStopping() ) {
|
||||
+ } else if (!isAsync && !isPrimary && !server.isStopping() ) {
|
||||
throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously.");
|
||||
}
|
||||
+ // KTP end - optimize spigot event bus
|
||||
|
||||
HandlerList handlers = event.getHandlers();
|
||||
RegisteredListener[] listeners = handlers.getRegisteredListeners();
|
||||
27
patches/api/0008-KeYi-Add-Java19-Support-for-SIMD.patch
Normal file
27
patches/api/0008-KeYi-Add-Java19-Support-for-SIMD.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Thu, 27 Oct 2022 18:47:33 -0400
|
||||
Subject: [PATCH] KeYi: Add Java19 Support for SIMD
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
|
||||
index ab5fea0b03224bf249352ce340e94704ff713345..42288a065acee7e3181364bfadb26d3c1dc6fdc2 100644
|
||||
--- a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
|
||||
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
|
||||
@@ -15,7 +15,7 @@ public class SIMDChecker {
|
||||
@Deprecated
|
||||
public static boolean canEnable(Logger logger) {
|
||||
try {
|
||||
- if (SIMDDetection.getJavaVersion() != 17 && SIMDDetection.getJavaVersion() != 18 && SIMDDetection.getJavaVersion() != 19) {
|
||||
+ if (SIMDDetection.getJavaVersion() < 17) { // KeYi - Add Java19 Support for SIMD
|
||||
return false;
|
||||
} else {
|
||||
SIMDDetection.testRun = true;
|
||||
@@ -36,5 +36,4 @@ public class SIMDChecker {
|
||||
} catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it.
|
||||
return false;
|
||||
}
|
||||
-
|
||||
}
|
||||
46
patches/api/0009-KeYi-Player-Skull-API.patch
Normal file
46
patches/api/0009-KeYi-Player-Skull-API.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Sun, 20 Nov 2022 00:20:01 +0800
|
||||
Subject: [PATCH] KeYi: Player Skull API
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
|
||||
index 9f762cf670bf5db9138e468e72e57781d8d22f54..f8bcea8fa62a63d61fb16a51cf7c05cbe09fc825 100644
|
||||
--- a/src/main/java/org/bukkit/entity/Player.java
|
||||
+++ b/src/main/java/org/bukkit/entity/Player.java
|
||||
@@ -3,6 +3,9 @@ package org.bukkit.entity;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import java.util.concurrent.Future;
|
||||
+
|
||||
import com.destroystokyo.paper.ClientOption; // Paper
|
||||
import com.destroystokyo.paper.Title; // Paper
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -2903,4 +2906,23 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
|
||||
@Override
|
||||
Spigot spigot();
|
||||
// Spigot end
|
||||
+
|
||||
+ // KeYi start
|
||||
+
|
||||
+ /**
|
||||
+ * Get a skull item of a player.
|
||||
+ * This method runs on main thread, which may freeze the server.
|
||||
+ *
|
||||
+ * @return A ItemStack of the skull of the player
|
||||
+ */
|
||||
+ ItemStack getSkull();
|
||||
+
|
||||
+ /**
|
||||
+ * Get a skull item of a player.
|
||||
+ * This method runs on main thread, which may freeze the server.
|
||||
+ *
|
||||
+ * @return A CompletableFuture the of ItemStack of the skull of the player
|
||||
+ */
|
||||
+ CompletableFuture<ItemStack> getSkullAsynchronously();
|
||||
+ // KeYi end
|
||||
}
|
||||
683
patches/server/0001-Rebrand.patch
Normal file
683
patches/server/0001-Rebrand.patch
Normal file
@@ -0,0 +1,683 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Encode42 <me@encode42.dev>
|
||||
Date: Thu, 16 Sep 2021 20:39:45 -0400
|
||||
Subject: [PATCH] Rebrand
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index 04a1e3c9619b41f429bd598d55c9e0b5abaff920..c8f031712006d95c59027791be1bdcdc2bd836c4 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -7,7 +7,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
- implementation(project(":pufferfish-api")) // Pufferfish // Paper
|
||||
+ implementation(project(":leaf-api")) // Paper // Pufferfish // Leaf
|
||||
// Pufferfish start
|
||||
implementation("io.papermc.paper:paper-mojangapi:1.19.2-R0.1-SNAPSHOT") {
|
||||
exclude("io.papermc.paper", "paper-api")
|
||||
@@ -81,7 +81,7 @@ tasks.jar {
|
||||
attributes(
|
||||
"Main-Class" to "org.bukkit.craftbukkit.Main",
|
||||
"Implementation-Title" to "CraftBukkit",
|
||||
- "Implementation-Version" to "git-Pufferfish-$implementationVersion", // Pufferfish
|
||||
+ "Implementation-Version" to "git-Leaf-$implementationVersion", // Pufferfish // Leaf
|
||||
"Implementation-Vendor" to date, // Paper
|
||||
"Specification-Title" to "Bukkit",
|
||||
"Specification-Version" to project.version,
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
|
||||
index c5d5648f4ca603ef2b1df723b58f9caf4dd3c722..bf670b956b20d670f84f1ef76badaae7f0c20e5b 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java
|
||||
@@ -17,7 +17,7 @@ public final class PaperConsole extends SimpleTerminalConsole {
|
||||
@Override
|
||||
protected LineReader buildReader(LineReaderBuilder builder) {
|
||||
builder
|
||||
- .appName("Paper")
|
||||
+ .appName("Leaf") // Leaf
|
||||
.variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history"))
|
||||
.completer(new ConsoleCommandCompleter(this.server))
|
||||
.option(LineReader.Option.COMPLETE_IN_WORD, true);
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 68d16efaf9c2d997afabadcf1ee24c5de685b5b3..c69cb21f2ccf0f93a7ec17d4ee1ddb0ba5cfa5b2 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -924,7 +924,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
shutdownThread = Thread.currentThread();
|
||||
org.spigotmc.WatchdogThread.doStop(); // Paper
|
||||
if (!isSameThread()) {
|
||||
- MinecraftServer.LOGGER.info("Stopping main thread (Ignore any thread death message you see! - DO NOT REPORT THREAD DEATH TO PAPER)");
|
||||
+ MinecraftServer.LOGGER.info("Stopping main thread (Ignore any thread death message you see! - DO NOT REPORT THREAD DEATH TO LEAF)"); // Leaf
|
||||
while (this.getRunningThread().isAlive()) {
|
||||
this.getRunningThread().stop();
|
||||
try {
|
||||
@@ -1656,7 +1656,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
- return "Pufferfish"; // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
+ return "Leaf"; // Leaf - Leaf > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport details) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 277e8a03ab270eabb6b8c31d0076f3310c91eef2..07b40f503358987339937bb8db5a3ee54c1b08c8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -261,7 +261,7 @@ import javax.annotation.Nullable; // Paper
|
||||
import javax.annotation.Nonnull; // Paper
|
||||
|
||||
public final class CraftServer implements Server {
|
||||
- private final String serverName = "Pufferfish"; // Paper // Pufferfish
|
||||
+ private final String serverName = "Leaf"; // Paper // Pufferfish // Leaf
|
||||
private final String serverVersion;
|
||||
private final String bukkitVersion = Versioning.getBukkitVersion();
|
||||
private final Logger logger = Logger.getLogger("Minecraft");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
index cdefb2025eedea7e204d70d568adaf1c1ec4c03c..38920d680d9b0d81013dcf16ce3dd7271eeafe4c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
||||
@@ -504,7 +504,7 @@ public class CraftScheduler implements BukkitScheduler {
|
||||
this.parsePending();
|
||||
} else {
|
||||
//this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper
|
||||
- task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper
|
||||
+ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Leaf"); // Paper // Leaf
|
||||
// We don't need to parse pending
|
||||
// (async tasks must live with race-conditions if they attempt to cancel between these few lines of code)
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
index 80553face9c70c2a3d897681e7761df85b22d464..3e14c02c2ed3d687c866087bf7477918f45e3719 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
@@ -11,7 +11,7 @@ public final class Versioning {
|
||||
public static String getBukkitVersion() {
|
||||
String result = "Unknown-Version";
|
||||
|
||||
- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/gg.pufferfish.pufferfish/pufferfish-api/pom.properties"); // Pufferfish
|
||||
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.dreeam.leaf/leaf-api/pom.properties"); // Pufferfish // Leaf
|
||||
Properties properties = new Properties();
|
||||
|
||||
if (stream != null) {
|
||||
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
index e9fa7faaa4451e36b3908cbcbbe0baf213abde96..6466e8bd54b38e4f432101c6d1a397db1066d341 100644
|
||||
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
@@ -155,14 +155,14 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
if (isLongTimeout) {
|
||||
// Paper end
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
|
||||
+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Leaf bug." ); // Paper // Leaf
|
||||
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
|
||||
log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" );
|
||||
log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" );
|
||||
log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" );
|
||||
- log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" );
|
||||
+ log.log( Level.SEVERE, "If you are unsure or still think this is a Leaf bug, please report this to https://github.com/Winds-Studio/Leaf/issues" ); // Leaf
|
||||
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
|
||||
- log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() );
|
||||
+ log.log( Level.SEVERE, "Leaf version: " + Bukkit.getServer().getVersion() ); // Leaf
|
||||
//
|
||||
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
|
||||
{
|
||||
@@ -185,12 +185,12 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
// Paper end
|
||||
} else
|
||||
{
|
||||
- log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---");
|
||||
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO LEAF - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Leaf
|
||||
log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump");
|
||||
}
|
||||
// Paper end - Different message for short timeout
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
|
||||
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Leaf!):" ); // Paper // Leaf
|
||||
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system
|
||||
this.dumpTickingInfo(); // Paper - log detailed tick information
|
||||
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
|
||||
@@ -206,7 +206,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
||||
WatchdogThread.dumpThread( thread, log );
|
||||
}
|
||||
} else {
|
||||
- log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---");
|
||||
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO LEAF - THIS IS NOT A BUG OR A CRASH ---"); // Leaf
|
||||
}
|
||||
|
||||
log.log( Level.SEVERE, "------------------------------" );
|
||||
diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png
|
||||
index a7d785f60c884ee4ee487cc364402d66c3dc2ecc..9597d58066bdbca302d790e6c195204b7d878011 100644
|
||||
GIT binary patch
|
||||
literal 13210
|
||||
zcmc&)1ydY6w_ae;A`29^#oe{ITXBjPcXzkNDekVtin|vp?oNTl-QBJC{eH#G%*mO^
|
||||
z#Lgr+^88Ryl0icuL;(N*XmYZWYX9+({}B@0e|c88LDhc@Xep*B1_0E@e|j^92LMpy
|
||||
ztR*B=T-9X6!E#a(JnUb1c$hg@*Z~09AGzwD+R2Z&!kdrg7@FeCSM}+3K>!NMDx?vR
|
||||
z&QDMhz&I3yB{~=uiK6)#2Qx=jV<31DMK(8br+}`_QY<P`H(KL6-v!xPS+l>-<@x#R
|
||||
z-`C%VIfrjk-qRQmOe~tjgP%5lFKS_e{L5tV%CZBaT@Y9t*)1R#bTIzM5`GW>xPtTc
|
||||
z3UI3vd4s8S1i%8E7FnpUhPVHPbg0m10l<lXEefo|PcR8;fDx8&BcA~y_<%a~Ml%#Z
|
||||
z3IJf|?I%tFs6Ydp-N^~V1D4B^*YE(#KZ(nc0I@KDOgb4VSkX>^kw%aj6KwAvKtYu#
|
||||
z1q-mZ1_q+j!XX0->4FD%#AzpBh#CPPnc_?n05BgcK!Ox|5)P~YSHL#cvsG^B6xJpS
|
||||
z1Lz%3olO5a$N9M}b%xOM=4xw)eCLl{y|^(RJ;(xik0K{Mn-W|05KdtV6#yW7p6&bK
|
||||
z6G=Ec*xNp^IJCRG8~piUd*w(WOn$xj@jC_<2mmQfU#=SN?=QhQ4a3yA_t=)}0ai5u
|
||||
zR-4cIoKWNfU6dK0=V))fH&N2OLX{Cg5@M83pU$aG3cJ{LqlN!*ZaZ#82R!`O`T_O1
|
||||
z0yt-hW>)tWg}gf(J9yNn#T||V#n~Mm4=F!}!vf#q=x2Ah>c2DLL|tqDXj7q39QJNk
|
||||
zOOzxZP2Isd4&=BdOM6F7_Cy0zg)8?ewIDW++w}%qz`#bMYtMNAL<4S_V+cPb0zj5r
|
||||
z9Nv!rKyuG>yeK0KU^2aU7XbKug#Z0l3ZB9c5&$4s5X4X?hKSntxvCdEr;p@!FCMHh
|
||||
zf}|)aRj(jO9AOVaj8cf7CPwhBmwy@9Tn9&3fSI)oYU*R>Lp$8U`W|%Zgoj{+pZ5p<
|
||||
zcQ`UoYy=70n4CWn(<E-0VhRZ_GY&{$EX$PyDFz=$epaOz9C0azEf=>*)R(2aVRrfa
|
||||
zCHA}MO9FHR%n|h#^;?ELC8$9aZUNR^wEY(uVboB8>#Q3WhCU?ir|m3Z6R8lS<!9OK
|
||||
z*CTf~fPYk+DP)!%-6Cei_<Kx*l+h1uLYiS*(|v7j&3JB85^Y`&9HQPl<4Yte*k}m$
|
||||
z8InOL=#O1+LV}F8g0{pj>NCnFtPUhC<d9JIKeQCdzm%J(eXyPfyiEA(6SSqPXfDV}
|
||||
z$@8cUXwk6^lVz#UN0auHP{^qhIOIOb*~&s?nTyqnh37!lISMqV3HGBKdq@qCDsXyY
|
||||
zYXU}sa?<N)|6c27{=vu{1>~PpYQ-s7^4#Vk`@oWX4)M%_3f0N-yal9+NdA0XIr{<+
|
||||
z6;}0#a%?X5Eb7T@T#4~w=Ay-!ENe^aM=RE2w+`g>5K^i1ne;i^BgEsw<B&T~RJ3rk
|
||||
zkYQO9Is#h)UxG6HRsz;cg;MzW^vscOY=1e3GA%POG8{Fu86Ft?a1zI`Qu$LgQv*^D
|
||||
zE52#CYKSa)SA6<bsew^xpy^*Kt<k8mTaLVdTe(<HqS0B-Q!}OJsTQv?t!h}*ZTKGi
|
||||
zVv5!f9wuE7E?e}?v~`FemK=A8!~9xXe91)<?v%+kL(xR9;rUF#1OAoBgVk3-UBb1(
|
||||
zqRJxCBKN>~5(a&!e(UPXN{;*#`4rleFEbpo2y^|CO|?aJKsE2G&uaIo$+^op?)mBJ
|
||||
zrMpwEXf9LkJ-<EwqdRg3PlswpSO?U7`b2o%^wj$p`F`vk{dj#==HC9U=pOIna_MrG
|
||||
zjF*iIi6?=;j-Ai+Y9hh($Tq{eZT2d3`xoZ8RY&50Rne?m5p5gIMTF%pw-=tUMU^A5
|
||||
zNfp<I`I@buv57SYw0NL+aIc$wGQ~E_qGPsc-fd!HglVm6xoY$*?#p71ZJu%W%5Ugf
|
||||
zY*>j@&Y*lWPxNrwYMS3Te41j~V^xNxu%@@>z2@I4xux%?OsDosT6QW#TG^=C{Mq9z
|
||||
zzpAsV2RyRvH$U%uj;EiazgKryWj}j6LpjSjLpcBPVEjP+VE-^pGC_<*vLxUp;OFAz
|
||||
zKH*{K^!v1Uo2$QkpuGQB%aX{l&^7m#8?W?h!Z=pCM>?LmeOXkQL%z>=>OSE`$6WLL
|
||||
zeNlF2_FDCd{lfZ$(4c?it0GG_(WrjE(52Yj)uZ-~^Tcj$S$5f<+k`__0}lfogV!!n
|
||||
z<;EPEyd^gK5$J&4R@b<%5x=mI`ODNXobZq^Y`#x^M0aU7#imd<Wx!HEW&q+_-mAdN
|
||||
z_<Q_Q&$jms?zIxU5lkP<K1^2-VNfHSEgTsz6Ig=C4Ic~NiNJ~~j3bVUjHW~8lI+-v
|
||||
zcSH1S%DHCAlr@VphLnq=OZ37vL8Cyrgc%n;jkF00a4daRIG$)hirkX1i)<saCdkBl
|
||||
z_Ww-Jz)`_+qS~bH=Ir*!v{bdH^J>`@cO73I(=GtDX>swetg^9Fvok%*ZiBQ{v;}!Z
|
||||
zJV{-rW4U2dA)o))8(1C?`myT@duW%%nX{MmEzQleW`FHxJKn+Z)Oen!pbocAf*)U4
|
||||
z23C55$bJY|T!j^1dB4m-kp%lDG&@XLs{3c`Pu2R?HhICMgIvwj2flRye~A~XaAj%t
|
||||
zAx>mvHAe45f~0oJTSZODrH!iT73US^FDW@GIYnw{)@e<Qf7x2;T9qvr8I#fWybtWh
|
||||
zh>|159``7pU2mZ{c3}#$MNMioD(JWhtiKq&^zik(+GM+Abr(1{Ej~`3DL)0{`gJAL
|
||||
zskGHKF1LB<TyIhINOj^;Myum_vasu`b(ncsU(NZCTa7oQy{qhKt7+WWc(2{WsfEmy
|
||||
zlt?fJYjLHPr;Ls})ZFQ|o8lO!nrU3xq%Z1e1~TBK8df<~{i=DYlWsfM(NZ#8^t<=A
|
||||
zUtQghZyh^7l|3y!b*OsO>8X|PvJqRH3BN+CCc2K@Co;5`-*7ARvAK_%Y?>UKgyS~m
|
||||
zKG&OQse;}V@)SMz<Ob@GYra=kwsx=3tS<Ged-~p@hmhb1Y+R<C{cdLT(z5N6^1pYO
|
||||
zy9i#7Cp01I=s5^jZ<Fy<9?XmPE%8Nskh(mzadWg=tL^D&K(<%oi6xcgciPW}IId=&
|
||||
zXL&X|=`x`I5!>&h-7NL<-Bmd%oa$fepWMt0Y`sT1mGx$v<L_~=VlJ{T5Gw4tJc=pG
|
||||
zB{3k8>2CcOaLK-F>ORaJua#GjODA;wyce9jTV__4m#ZWqw2-;x{iyJkX{)cQ-(@K=
|
||||
zohO3lcA?N}_&9pIaTu?E_1o!=;?V?3-TJj!s76R8!0CNkwpP#a)ckS$TuZRV?N0Gj
|
||||
zVD@r8@WrNg(e>}sUl#p*@2<<CGon@pnswqf>W=#-kB4(SPm~LVHGQ9WuiCfn)%O#`
|
||||
z7mSm@rjL5_Ui+;lqh6!wejSWUbmWM<kCcD&5!-Vz6EcgG(v-3BxnyKSXoOuiW>d-A
|
||||
zWesK6(_;ae|GZCKD-So{cV53vYridDeR__b?y2!Ezje8+EU)DsrW_{wJ>@NQUHVo%
|
||||
z1@*sdyX@E;?jp;idlUUoxt)D69WI+ueiT0R`*>r048472mf@TJPss$E%Bm>>06sJT
|
||||
z03;Luc=@jias&XlvjG4nMgRbR1^|HPl+&Rq2mrvut0;Vv`me*kfB!x{KHlHo-`?I{
|
||||
zUtgb}pC29`?(gq!Zf>rwt}ZVx&(6+HPfw4Ijt&nG_xAR7c6PS5wl+66*VfjcQ0U6a
|
||||
z%F@!(;^N}`{QS(!%=Gm1<mBY|`1r`k$nfy+z`($tKY#lA`g(eLy1KeLIy&0h+gn>(
|
||||
zTUuJ0o0}UN8tUrmYHMq&s;Vk0E6dBv%gV}%i;I8${8>;?ke{EQo12@Jm6e&9nVz1W
|
||||
zl9G~~oSc}L7#9~86B82^6%`p784(c?8X6iL91MX#0s;d3{r!D?eZ9TCJv}|$-Q8VX
|
||||
zU7eks9UUF*?Cfl8Y^<%VEi5d|%*;$oOpJ_-3=9nP_4Rdib+xs%H8nLgG&I!I)KpYd
|
||||
zl$Dhg6cps;<>ln$q@|@LB_+kh#l^(LgoT9#1qJ!}`T6+xczJobxVShtIM~?OSXo(_
|
||||
zn3xzD8R_WgXlZGwsi`R`DZyYc85tP~2?-Gq5di@KE-vop&!4fdurM(((b3V-(9lp&
|
||||
zP>_+45fBi7Kp-qEEDQ|He}b?I*$DVgBw=o9O6va=|KAh9-pWAyzXc&X$?CWQ0O$k%
|
||||
zBbZc1bRqzNCSFcb?3-84xxbDp)o9|zA!ee^Bh0sLt2Ik936_Xrk7kRxkdGJznqzah
|
||||
ziwmc4PEn1*@bP{RMH<e`JI_0cWV2En%hAkZIMLm1)yLdS%$kTQ8)AJx1qM1%!+nGU
|
||||
zz<V%#`(oRY3iIP1__~a=_w{EW!cAe~i#mpp5d|9nHmH4b+n42RU_J0cz?OY$dg$G_
|
||||
zT38aor7zw2SF~3=2?6zj5d_QFU-hTn=yW0hG5ojZAEn?QNK9d}EJ6m6JXtK;!c$27
|
||||
ze|z#${hqwm8Xl+m+R}BSsl{~1<b|KD-oDn(vWxE+)KF5zHgF|j<j2roUL7~WBFFmD
|
||||
zQ9_Vn6=_Vz<L90O{qO7=D}Fp}Od_!Z5r;nP8s_oku*n4VS$zSSzBH7ul13;BQ$iUT
|
||||
za))bOWklxv3NgN=%}7k#dgbNhDB3HFA+@}=q!KqmKye6uR`&Pty{p0P+v>3}a=(1D
|
||||
z&|*aJ%U%R_aG3DF7wg#&Bbu!|ou1+!pgaS@Ns3((VSm*HaZpg^QQjodC+i{Mj}OP&
|
||||
ztW(24-;seiIG6#yS_?^7;yit%kn;MEDkH!Hz=G$|o`f7-`0YBzgo`)ObD3Q$ZoP~k
|
||||
zs7{(p@o=KT^XlxExsy5i#c<41UOUKC#P0_Bo87kuYG<8rObT$yw+IDNe8LFK*4uus
|
||||
zZ6zXYgc%s*TKfc+1jr)dkqtu5uE`9zGLRrtuJ<_@xsj+r)hj*UQ(|swyXobaGy9TQ
|
||||
zA!``eVdSyIz8ocx)#!V|NG`z9*RuacKxNy(NT*<YdfRV>N1JpLTJ>Tz117n7S<sJ;
|
||||
zT!;u=hnoGy<?bRAjjS3SHmyY1KNLV<EBHI)F9NaheVa`QJ3AzTDh6LzCaz&rn^Si`
|
||||
z7KK8-JY6C(v&nhYj*djIoJFlbB%+l~*cR4=9NB}oFLGn(tUy2KUFngHqlTFSa0)u5
|
||||
z$@oCKK`W#Nd6U?ht1>d@M2K&N<B>*bl<@&~`3=F(TV(kyaz{i;Zw|xvrILWbgLG_L
|
||||
zQjYTwQ>{D2P8c#l5SxtU;cx?~rfXPH5+*PDQwY2`EEuF``U#_Zf`6nlEcjEmDz2~{
|
||||
zcz~gq4{w}DsESKTejt2}2;%ok%#H$1Oj?Reh_F<X6ZFE{$;v>Ay-r0%b`}E(GtxF~
|
||||
zv|cP%b87Zbc~JQGSpb58hXhj`D?6opux>N1Sy?vhUh7-H>i<hL1Gy^P(z0kpUMgJk
|
||||
zB%%Zz=@AQwoU5HHT&Z2i&V0(#21pNZ?vE7t1_mq>>f}shs&QjtF0MC>&!8?nDlWr&
|
||||
zSsC+$?$mRqoD-8RG&?eFh*VQk%)4GsSo)?)npL-WUL>@+mpmB-IT=~dD>C{HZ<8PA
|
||||
zT(k~MTHr!3@FTeedEXgx9DOOt9Y}BmUZnl^=Oa);u^QE9?W{X<2uHt^MUcQGwHjO%
|
||||
z!qyKR%x6CI<q^m4K_jHJlG^()kLMx~C1tVdhH=TX+Z)estmHew`f<M-Pn@Uw%k&fF
|
||||
zM8caM&3>m--w;HNm)6XRpe60!>b7QP&iJX$IeIqT+6wKbXLRk>@)YAGq80Y{5{--z
|
||||
zdUTSsK<AArtRIPT)ip{u!iMP(CnE*nb9eCF+qyp7h?dRuHNRLd0ub09?MRFh0|fEL
|
||||
zQvbGQ75*qxIDA@AUf*D!dqf*hW)Xt`#gGyb7O0&wi$Rh?|FR=RC4)t=mS%QtRBGBA
|
||||
z4SJWokYaZ$9BDVEbS{O=#`Zd=CybEDQ&Y71;nz(_!;KL*ZB4nh5JB+lI@kNd<r9Yj
|
||||
zMDUJQOsR(J{Py(=n?fLp3!0>26d8)bI{R{m-gW^jkyhhnd<%QQviY0uJVR_mXv%{J
|
||||
zWJ-IQ4~A!p=iApvClQuYwlJq37y;9w0JfAC%Gtti90aIQT6rK(Wh02##Kgo<TW-r=
|
||||
z_SIWd0sB^LdDeJ37Dszro5EocrR?*-@0X~+y{<-FQBcsxm9`HZL5dEz=Vn#T8*udg
|
||||
zr3|g!g6GU9uL!GNVd;9VP+Dh#N>xP2wPXL?bH+CxGu(bqnr5#2SFV_n?~BG!e;}4;
|
||||
zAO#jU0rcnJ<Zx=yVh-C7TCc5lpJDBV|9unOPiS@W<ELVQf8rwpBMWXEIT9`NHO++f
|
||||
zhZP^RJpnPYpu`kSu$5j^BruU;M1gdIV9y<QMD_Ie-+FRuEt!xHYn7Byf{_F;Dn>~;
|
||||
zK3vX>Q06d9t!w*+JL1>lL1biT3I{&wGL<a7IpQCB{JzkfQf_G)M0!{j$^5m$Q&X=;
|
||||
zf@A3yYN8}fy8vs7;w=p&C6qxQz0M=nilj`Kz~clas?Y=q!AC2mkl#V%;s~|_gO;pH
|
||||
z#4d;ggRd~+1E}PG)IT+j0&-5SuT|SOj1fk)N(Z^oO}`JyGR={R5KIAVrIR7r@ClW_
|
||||
z-(Gr2LfbbYVxG>$gJC7Gzb4NrlsY%Ks@S#FN-LxXeSe0RYy<5L^ph#j70FpNfGWMq
|
||||
z292pJSU;S0(AlUj;Un2le{CJj{c$q7Z@hia?N1vAo0xRhb-#K@BlA#!ktQC_hClVZ
|
||||
z{d7{=&Y)htmZvqj5euzk?dHFCz!3b+3RcMq!^zk8OBk^@6%as_noefJ$~wjZoU~xF
|
||||
z_o@h4<H^gFP<1Np`Njt%3q4z8ON;`XJ9TP*jmk7)sy+=LN^Nh)?eFOaCCmUp;{DOl
|
||||
z7<Nt5Ev-t~q~H}uMkMuDdSnndq1H<d6q+)pHr8?`+S@=~4^3#4`2K$IXvt(J#zqpa
|
||||
z;dC)-BJ22`UyUB=XsEa$_m09Q0U{#E(#|3pvn2G@doAG+Bix*zv@oR}rdS%Bn{5s*
|
||||
z`6f<Jo{A+e4p=)t()FE|Cv8Hc=!aOJRXl~f87k)p_<fb$UJt?taUpA7m+wEzdfdAO
|
||||
zn)aLrJtbvf&JGT<!$U?5Co)69_~cuRG=Py{khsPE)!+|_wPr?SgzB!@y(~^|73Yhc
|
||||
z98WW57`Wxp_K0M$rg&bDPt0{YUxSDmr2p;9c!Sg1-8Ay*QTEUzY)y%$`6#fOLce^x
|
||||
zTTC7!r-Jb{O`fMM&5kQ;89Zb6av?~Rvi<TR-!q;#wAS@DnLSsukF`o`<lnbci)}5Q
|
||||
zEbxf>hw6CpJoJZ;`Ql7V%7*QP^*31;IyLIng;k_ab_1`Wta<+~DKEoQ@4Eox2p~CD
|
||||
z*0K`yjn!5AMo>5!xB~*@6fa7~%<j|_Xk?!VUzyKyjy<)W=42{MKTQ6<Tt#yN4SPwY
|
||||
zrE9-SSHIZ`bl|zD3)-Aq!eV<EDcb+W<JwZMY9-HO=Cr6=vgAC96%LP@LC|f8v`q{A
|
||||
zA(SAmI6<Wq*r1VPV55Qti@Lc8lsI*<-qQ*sX}ritXa$OcEku171aJ0?DLQ?w+#0Q9
|
||||
z;YeA^*id_q`0x<?ddz3zm{@2g4^OkVC1q)X<vE=lXA|;%;e8JchZ|FG9U|Ohc>=#3
|
||||
zU@OB91zyo5zT2H*u%hsagt5*yo2rqwJXz5lUI>cNA{*;ZrgO$Xtt_PYsE*??(M=}7
|
||||
z!Kjn|zXem?%?_clKif+dx><n$Fb8p-pCG2TkWamOh;9&;))Xg1ubKce{?%i~7x53s
|
||||
zC{_EZ&*ghy!|kNS;+4_Iv<5}r(q6wDG^cynAqe@e5QZk(WcaA`&zrd3B`8X#QHyD`
|
||||
zGL1b~Yrg$oNiF4jc-O_PE(PgO8PX|Wd&hgj9z4tz_ZP4Oui&z3<@+#FCI_bE$#uTs
|
||||
z`&^3QTR^86#D_>oN%Q1dEv1sx@Uu`-G5J$7G()L>^oP}zziqVvcVw>iixpF=Ps{6B
|
||||
zuQ5j}{LBk6xiS90($ya|`Bu**41tAe^=_0<)MZ<Kl@|Yq``1!Y**|bWW;@$5lubS_
|
||||
zZ~NXvMn(|P;nY`A0&IMrJE|WK8!yI)M(3Uc`a<zPR-D1b1<<lRMV+r!7)A|AUzLY$
|
||||
zU!GQO-w&WypKWQ<%4L*4YzzGF&OLT{rp!!5cUb<Lf%A`ok&4^(D1HO&be_h9{#S=U
|
||||
z3XjE+{$YAA+G$T4={fh(jyqY?i~+?GA|W4BV_JIA#OGmCZ`Z5WdsoW>HlzI6M0ug-
|
||||
z4efyaE$C!Nkh3Gg9NKD+W#E8lW6ZR0CKhAarf@Cib*y`SD;D&4Kf?Ou?dUYN;w#`f
|
||||
zcEvIYw#u<W?07bN8VQu;#aB-=)xA>X-n*kXxJHYU>(528UR29lvEFggo%R_9Oy1{N
|
||||
z)9Q#23hWK4muc)VVEnzt@CER8E*J{I0taa+X4P_{JYVx+0Y|ph=0>u7uk0Fk%4`X0
|
||||
zYr%j>IVZ?S)9=SDGGhc-Qw+;L?PEjIEA2iI7+mpagN&D~9a?MDkjTjI1UZ3R_vQyy
|
||||
zrky+6ajkL;M##Heo=ZuiVPT<G4njg!cQrV{_(r%%u@?Ok!7HAVtclaa!Ocq?_j|AN
|
||||
zf$2heh9aJFKlE%k@lkP5s*d7(5fOXnK?IpP3g+2RW#yb`RACs<(0~8A7*q|IfOVI(
|
||||
z!wc?3N=h7!7tX^tjAG@LCmp%6m!RSqOS@XV@HJ-+Cd~CscpdC}F@U=Gq9h`NF=gYI
|
||||
z&pMPk*KIuU{dEO_-bTNcCw9yP^D8d|1s>mw7MY{T*;A;uJuYrm5D~;t6C_=XIr4>;
|
||||
zmu;`5dT`;u@`46+%X}S+6?kLKO2d8kD2zN{>oUB9p}^*c!Rw`$%zi4=<Tme61+e+(
|
||||
zT4vcL8yEp$hcUHxL4m_iXt{#T7w@MX;HRhy6Wm^CWv*_sHh*Q4e$ji51gjH6Q%oEy
|
||||
z3)Pw3yPNOsn)$=76K}jKAyPTu9H!M*Gh{k)Mh%L6E0M{H-Xi~UBFKq9nY>5a!o~DA
|
||||
zL2;T(zT`Gpx3dWCb4Vt@nvPG9lQ$8fz6=$v@L?L+a*uu-QztN^$I2V`>s;jH1Hpwn
|
||||
z?YPl-zTJ$RO69&u0C`FqHt<pO#?U{wMjp~fS}MYB)!LVw4ZrkJaIlMTzJ2xc`CYGW
|
||||
zx5<HlX9iGf;mYe~wBTn0QEE$;mF}$MpPz9r7Z7P(iW^(G>LSw@iWh48@qJjUga#zr
|
||||
ze`DB}Z=Z8(8jtBcnwans%w~41y5woXEWT_(#s`0`u^>6Dxr1)$e#Pf*=1QBaa!kM9
|
||||
ze^Po33_oqrmephsOpz_a+Rlj_7+$TmY5qq4ca?%mSb+16T3BRx<BLr~-#tLvkb;Aw
|
||||
zz=$9H;z|Yq(WENz`3GwwEh`4pubOY*pN42ZzDv6<DiE9Uc)@8#+k5Y~X7hLZu_J8;
|
||||
zNygaN_gs_g!e!Ky9pE=QK<)Vv(d*|85Yp(tj-Olg?@s+wOFEBv-XRe3E??}JHPx4_
|
||||
zs9|9=GsqdfC*QAzFJ&FR3!oO~<+}WowrG3?BZ<x$Z_j*vB;`Krr6&`?$L9~95>|ny
|
||||
zshR_a*%;?s-D5hg6nv$RVHFThATs#UJ5E8-#CLrVhjugF7h%84KuYYgfQ`Xs|Er=_
|
||||
z7W7jfVm7A5%#0gDozK%wn?GjJ1>)hN$eJ_Jz9<_PKRf9s^F&?(6*iLnghLX6cSX^n
|
||||
z+D;y6m0sL4eoum)5P&fnK0#hqY{t!jShD1!bL$TV_DHnOYCsH%HiaW9hi(<cB?^w(
|
||||
zdpb|jN>v*J-vk2)bk@|=F2Rlp8)^hr=RBS$lhNa5Ch*kKc<NM?#SCEM<i?sZ%TCSe
|
||||
z_qf_zS%h%;g=m$p=Xh54LSh=2t#g)gvwQ$xAe&Sf>E2)Thbe&>$hGN5Yr!?MzQ7j|
|
||||
zfwYnB`S+qCaXsBWBO42j+gtfYGRs8kmSy{vnkAgNx~kNwQ!Ina!9aDeLcz?!caBZI
|
||||
zHES_hJWng}{9=We$w?|W#(ccIb7Bo*8nG4u^4r73xU-N@1#6imbX~2XaZpR}MVlAK
|
||||
zX(XG<=<)2@$+JObDhi6zu&Jq^KtioFmj9~?+xXVZjsic+M43SL@L(yT$>dxVgMKZa
|
||||
z0oiS+YGA+~PS@#WzvfKbqtDSrY!Ilx<kof8&fRyqWM&|w?!s+#Qo8fJ!PQym?>-Gg
|
||||
zR-$6>Y)w+ZOjtl<S=gajY(gy=2jdUp;?v77e1Pu|WB;ww^CW0IGWfXdWxZc)f`P4>
|
||||
zFXi3spSe!tazAZarF+?8Rq9Ez^f)JJ=<y9JoPvUQ)K$oHW@2;I$ML~ZK>KNl4Y_zd
|
||||
zVD<h1?V9q|Ct(6fpkS*-@F5xf5*8>fNh`B>vN0a4S|{GOw#u-CDiCW?uW8MbZU1+E
|
||||
zqRWOXDNiXzX-c?Gs>Z#kS<8W6NKx@~40M5|^;Kk;6|1d98d<=q&)&N&x)s5QIcXPr
|
||||
zc0#$eRc|lqMC^z*cKWkyXh^@QQsv?=t%^zMvRy(e1S2ErbUc}#Hq^cioq;N|sF4>n
|
||||
zzdxgYov-P+0Ky$v_u2YrYPV<$oUnCu-jCDp2<1GR+!p*CRXLR+Cq;%2p8aM2=`>w?
|
||||
zK3A#Jpi+}4RcUw@j8c-GE<IrLP@C7YR>jD{?1ocBZZEVdK88Y~2?hp-;vN4=XN^
|
||||
z+sRZNq|L}7j5CpMpYM%jmLtAyB48v#nfOicrMx5+CE0S#r^rA+sJtaH!yw~p6@{Kx
|
||||
zxAVq>=w7z$03djFYmBzKrJMYt-%BW6d~B+UFK+mbrHUFgu|DZ5@^KC^uh;}?6BLz>
|
||||
zKIGbq11nZKxCQHrQ7Zp_I_p?riOg}YjnaZ)fcg=nt*ii_iAewxqIdTDVU?Bg80JWq
|
||||
zis3WF`pchWPp&^}2$D(0nm<<RuTGTF<yp82hbxBMbnn&2(WOmhwV7@>1rp${96w#J
|
||||
ztP~I0n%NA8O*MN?P<+;S?hhZXE#K4|0;!1(U(WfT63ha@eDz$vUyfe_`junc9W5fa
|
||||
z_^4#HgGBjA<A?tFvq5fu9PMpV&WqzuR(O_7U;xU^6ueSbbGgmZotK?IIjnQHF=Dv>
|
||||
z=fTq}`c(9AGM-NDU(FGMZ^pI71=g5}8!|zLX33X-_w7lI%7}YiHKI?5F$++w-pq15
|
||||
zQ)R8ejL~T~sWyEXZexwVPcu!5!OzQ&u1b5v(2e<8sEAdCM$}U+eyntFcQ_a=K}hz@
|
||||
z0bPD7Q%_`%v&7d5TMgZTajQ7*40l6D{-G_IX))hv-TKrA!N<4`YnME5Z1JoN$hBmp
|
||||
z83~6WHv;f5$pRR-g+v-2Rsx?M^3j`uFWfR}1}nb_mb=`qo+3JkVarQtb;+OCIE-Zn
|
||||
zJ$2KDmElP@W+qpwSHr?Y1E0NvSd>h`#h)jtFmvCIwndJn<9eP?K&q*pgf*Zu{cfTv
|
||||
z?QbW#8k?l&U0gsc3VvdUy7fA4e<x043J4fFluq`he{i=SAR%dqOS?0J1x)JtgGaGz
|
||||
zJqgCldD`%!+FW}%vF=M`A8+I4!K+Oa1zOYoVJy`(hfL<m0eVJ<N#&ux^4+;!?D5>f
|
||||
z9B@5o?zgVpsI<K5RcUQ6UV~0%AKG~kuFU@SQSLH=adO_QzN9>xy|0KRS8K~UH|~Gu
|
||||
zxWR|j9m0a)8Yh99sm=_&poSFAc)8f$TbH~3UEzhD1&UHxT3~19pWERGnU~Q@Ts$2e
|
||||
z7!*+!dm48og=(to#vca8_N@5T{{?*G0<TH;_cKZi<l`sG9xOe`2b6Duy=9CSW@M4>
|
||||
zlgGf#*Y80{eG1zvE8AyftcJwCe{OA3XVNoOOsr0;=#P^AjuIL;osF8<Ro8z^8p9<p
|
||||
zm?S&6vDD5PS^U!eY)}%gxY?G7G*B0g#nGxqY$ooIfVs2^9Ks#Ct&GrnWfpUK$UhHI
|
||||
z>dE~0*v(9^WT|Kv5d}(j_q<_zHw^6ln;@QmgIwixAJ^`6I$@NyZN|3A!hKW|{wG=t
|
||||
zoD*dZ4f~rj)V&ZWjjwXOUv9WR#nZByHoTYX8@AFOBfnyN*?TUPPXK_I5%$5Cu)RIq
|
||||
zO#_0fB6AtJNW%N1&avxJhT%HYt#3r%zZl7yV#J0oMTLz)VKBQtg^sM**;RLUsozt<
|
||||
z>EaQU%*}-uZab1c3S@<{L+&#AvB$qUzt~+K=gEY_M1>-qcLXi8C18f9M#3#-k<RcX
|
||||
z7MojfDbnTm91KCW_MHv?g}`9e|CnGZZm52rG^r(;uFe<w_x?Z|ITgr7WQ_2YT4>~H
|
||||
zAUQ%}Won8HU0-BZNlfpLwV|sbvgUu9xXmPI2>EQ5)Q%V*l%KI3&fHEa-%##X@6pXf
|
||||
zy6s?f$itx80{!nNkJrPeh>~G!a)1$<t<^Q+IQ{+eMJx24<#1eu&NORkf89Bf9HfAt
|
||||
zxmq&RYmUVfvWszc_Us(XE*m?-y+mPRjIU`E@WQ)tJ9+-VIQp4scKQ15`^LoaK_QHU
|
||||
zZh3nNB1~=LzldC=OJfGBep`2zTW%QXFl=1i#UNWJV07Vin^jJZZ-~B&y>x~g;B!_!
|
||||
znYgLt?%Ir0xI)N@K;Uu>xSb8#f`>To?E}LyP%3t^wk2ChIk`L`7<%ztsjA+{lp2dc
|
||||
zul7ic1oNPG0B-zS+&Jl;UL7s~4l~aHfBenF^L>p|MISq@kF>D;(QQ-zN8B(BPX7B-
|
||||
z(Z8hEoxNwRY&47Gbc}=sjSXAh^htV3q#!T1X8p>?=!ttolM<SU8Ge2n)4JGBL#-ZE
|
||||
zoP46`T2jYzo-j-y1atBx@(bcP#Y08yOe4FK|1RQRL7h!H->gvDca<Lv`(uV*4&-6j
|
||||
zLSPd`yR~iC7bniKgXjhG&|UU_nJ_tm?|sjQfFKH2^+G>$&z@0)0}Yd((7meDa~unt
|
||||
z?6;%gTjPb+kL%O<a73ON1kiv-#&(O4@q|=*tA#cF&WpDtq@Z2}1R=~LoZ=gfAl=L)
|
||||
zxIT6_F6(_Vk#EM}iT1xNXrA(=!OYJk#w~5TH7RqI6Cn5nVP5hO2-v7N>;jbP*UqT+
|
||||
zwL^77jqppC&&-_8t$I#2RB4@@SDKCGf8Cvh82ZpchjY8(ze#h_3I4lQV>rzfezj>`
|
||||
zQP&EN1Xx3L<{b<fd(;+|U)C@4(k^7to+M_(!F)UdO}bE_t1uf-Uk4ARLS5N^rrXVh
|
||||
z!M_t#DOko8ZNZ%W&5N2ILI1_uxj}k39tFKd7()hj;|pTk@?&}bRu=P7-BJsg#!7)s
|
||||
z4LBap6u~=0Sk3ax#4|kF*Ts*svsE!)G*x5aS|R9$ExW!fMToX;A|R*K^iAZ6DmHuu
|
||||
zZOIP7t9?Lvz_OIG{pLe18-XJ==<gz{%ppy+-S&Rad|-d?){!J}W$4nwW%p`@&p`Uv
|
||||
zc%-NY7oc^0d;G0e9MZfL+@ZRq_d|~Q@IN@s)U{@Fr9T2YqQQTWp-4G$A(H?6?CU2b
|
||||
zTC<E7<mf<JJj+{vQfmu(c8%lTZWQ;R!Vq%g){`xths+h;O~*bl2v>Nq`~<7wJ}07H
|
||||
zSR9#yKjnW0c|oLtA49d<ah=b#^e7f8ePk$VT;QclJoZS@^$m2r#@%18j7>BMP~EJD
|
||||
zXKnKj@EG^_S5&;$^FWYNqJKQ_x_`xRKS~d(_`P!)Ec(XRR$qF!llii3jCd!{q!ZF?
|
||||
z+!8_d{xp2sgVT<a@(@SpFK&TKfNJSB?%gkMWE%Nar*qVI6Ce0yb~bKj?b@}qUO&2m
|
||||
zb5f6Mn{dz@5|+4jGUYJYsq*D4kqs3`X__epfip8}>@;059a6ah0}CKP6>Sx8L<$Ag
|
||||
zTPzo9+t>(_Bve)oL#L+%%@O1}4B%j~hP2Bg8fTkt*CifZzTgKDBrfdTg-EhI9;-5%
|
||||
zH!dX!eV=qmAQy!Pwh77BZH<-KX#*+C6KA&zoe(NTydPY8_7d1#t~y?|L{S^%S*9>D
|
||||
zUmi4f<&}OE{<*F%|8bZ8Y?yPFud51sU%hD>Tu1G;S$uA97K$TVDkB|%Z9C#;0OeZ~
|
||||
zvGoDo(kLbggJ7}My<EKA_VLQ}Xc2ZAII;0b^D|__v>NXFtKVOM90amFI~|vbs7PP?
|
||||
z+CrR`_O);#spc?-b_==9^akfc`sLSQdP9RI2EU5RHjo2p^J6L&cgs5S5b*>1S=i2w
|
||||
zme<S}GA08(e)qV4YlXideY*b%la^-~e(t?dEgOkEFlGgdPbD$Cw|wNpL07jb_(fQ_
|
||||
z;;(+dqW2q(DAHMwf|;8$Md-XG^gfTDf~{(KWMI!r`+98jqffP-db0ZdVQBU$2g(uf
|
||||
zVS(|Hc051<Qj95;-chyXhC1Zte4b*6vjkrp`5a?}!sDw^<q1Z)c-t140UHrA(A3?$
|
||||
z0%%Ak_XYNoLqc5U)p;Ftdl3*E_TS1P_MuFUCLq*e+$h*>SqAQ$I6VThfB?S$KQ)II
|
||||
zg5rtw_UQo8-hqO>owrTP(`+Is41{2KPVGU9gVJzwi)OD5e{CBVUIE__R6-aJbP#jy
|
||||
zk=_n30>~_56kRG}SnY=wTg02q?$+K>)7lMSg<0M|ngE8g>T2yVe2E|Nw2UNh8mk|q
|
||||
z=@Q_4^4IpjvGw6$il0TjHGhXjp8|EQffCw^B9J%>`8Mn3<Hm(s$1&0rFFzb+(!3uO
|
||||
zd0C<V8!eIzNtw0e){t0G$f|EsAfzz3d~knTw8go*$J5{*RgyK<Q(^_56TF7&d$W}D
|
||||
z8GBsT%*>C80Ii1NF?z^iyXu>jwS^pEci}%=dp#5gh@zRV+-3MwKm(}<PIq*9@9nPc
|
||||
zPQLTBOk)=j+u+<{pg=f;8#Np*qY{0f5?d#MrclGmN>C^<#w_u@sZpOPC(U-~ejX_x
|
||||
z`>7YX+E(;Gz{H(GM)WDv9R?w&n20!22S2vTFW|wYapndx?ry>BhTC%@eTJ=ICW?dx
|
||||
zXC9$ev|HrN7_oS;z2aRybL7>f;&O@L*sq5I(k&?qZxGpB=X-p^RZgQ+zf~V47KZ9=
|
||||
zGI%4n$yiTS4@klyT#0(nr4bT+9SA_K`qrwX{HfWab6Q4qBmA@I=RDc+#jf>W2?StT
|
||||
z(DwfGH=tok_xgGz{%wuGceVlol|CyMGp<xrRhrGJYO<Wv6B4upM@iI+Pa8-BzqWrY
|
||||
zkI^E&Dw@C&B>G)BnOHF!imYzX^Pr(=K6`RvZi&H5T;GjcsVJD&-Hcv58*l$U{@K|R
|
||||
zS-Z4(Os)d?5m#1q*5|xP$IOKofooAFzLMJiUR_i{izI3EMFrf>ii$-FAN=E+i(n#>
|
||||
zMdNR^bzvd?T2JDCrxdj}F(D<Jj&MJdFm^JP(WeC1>_EiXhFKFkhn;$Q@PCUg3_>0G
|
||||
zY13U?VYjUqggCH1tunT!T9iBa=-OG?1Fa|BM)AE52@;DaaT#cFWW!P8gbaws4x*-8
|
||||
zFc@nLf4|8S!F0QtC_MHf`jf6#r>c`OPJ)=s=`slkh@!Mjs9&RZR-Wa`SLX=VW0{}q
|
||||
zX*<XgR0Juyy>y)lF(Va3vLZ((wwDgPD|>vYdO<*}cL{-yL%L-)REcsU!Aw$;D1?%k
|
||||
zscDa?>1lcUX>&p<`1=FVpQA@7%1WO|>vOep@;|tRh5WnS4+<S`8El8C%Yh+J2Q>PH
|
||||
zFu?ype%rHNTol0HHYG0Kztny~M>tjUA_5miPMm9f4;K>t=R}oJ-Ltk_;rr(fjTU+R
|
||||
zmu(3w8!rtvn&=#gv|5owxr(-V{Za*vva&pP+59Wgg%R>BFM>(GEiYPdk#d?^`*&kc
|
||||
z|61z-G-Gz2YI&g@o8t{PSTHkVnnH=1gjlB3NA!Wi_EXi`0y^MiHS{vSHS(&c=graZ
|
||||
z>@6P7*TvgdmcNWB+fq?1+|ZU12tX<<P5&t~%|Q6>S)TUalSDf=YQ~qKV_K`jnwyhu
|
||||
zOQMBz9ypM&Ide}$Jd*!jiQM?wqckLvrO>zHTd(irk5S?%Xo!RzwK7>@2{sZ1TEM_r
|
||||
z<HJhp{uprbaicT(ZzI-=QDvzvE3>+H1~K{XACzG7KW9A#byMA6a^J<+ZjUz_t2?0F
|
||||
z298^%FiBOujZ#KP#$dt0KPWWn$9GOtby<Hq)P-4d(<`Tpkjoxn%#K)vKh6&$WGJH>
|
||||
zS{~hM59$Hf4l2y)QHJl_`P-M;W_o>+E_6blKkX;D3f%AL6smaYKcb=FZ{kG0?@gDP
|
||||
zoyYX&-d3-pyd`C3yA@xVBBs+u<Ew>7$Rr<2(plAlp)6X;<Cgm^-pR7tomiM`FYlNC
|
||||
z4x5#_beKs~2uXI=OVw)H6;P2%g0BaztoT2tm~bC1Fof;iHk^8|>n4cA+4Tss1%Jcn
|
||||
zZsntDp0{55S|VSv<WbDd8(D1TRNF3%Pe*_%6_GqD$;8w+;-P#0=h(Vr+x_(LNdR7)
|
||||
zm>{qzp-$`8ZcVz{&Bx#u!6m|QdpaWwIMh61w|rZY!eU%uitpZ~{Tstyfz{LJ4l^(U
|
||||
zUAnKbD436p|K5nM{ERrk{WNU8%Vd!A?2=2q`vt3;lhN1W2Q^&co(e-|48u=_?sX;{
|
||||
z<xjB|z6A{RB3K|~`><q*Q7aD8=ITYiN}Y{O#uk3a#YLesl|k4BJZB1uBo<|V|LlJe
|
||||
zWdl#$RFmT-%}cMBN%w_8csEPOK@w3}!tkbZBc?<pDy%|cj^;nl$KKVuHo-kQI`Mz0
|
||||
zF_{EX6ym9Oj8mni&KDRL)yfx~nhrc0gf=EusBb6*#6Q6?f+9=jD2v#elWa8@26Y>E
|
||||
zz48#(Ii>N%SNbF=G8H7NQ0rD}(xV1V8ZW$fts^d@B7I7&YE!6^vIxJ*+>Qv4w5~r0
|
||||
zPP0oBU0nE4z-~M75!d~9tT{gI+6<b|yoXL?;A2B>Agrt;1W<oXt4Y|aR7@kIKHCGg
|
||||
zltECH*_q7<3$~UMGpf~K#APUPfgU@=z?)pK4|_JI^&o_{K^0{I5^RhDIr1gaSS?Aw
|
||||
zpNoumRY9@4P4b6f;w!VIcqt&saNl$4Knn2tM}>Hz83!f`LP`TL6s*E4Td}UxrOBLL
|
||||
z>6p{m^%3LnbMIc{MIgVc{HBv0NumX(2@b}bKKjj39RRc{o3G&2BboLcj?{f@=dJE^
|
||||
z^gGoHj>M7#lE1yDhvq9?#qhi+Hn#Yay`7Xj_J>!ndQn{XzvqnH@oOUkZ$#cEo~B}c
|
||||
z!N}c{C~7^rNt`X{SNfDcK4Q8DwAPvQ5It10V1J-<bn8*TJiuj1&UCGt1CkssU-hfK
|
||||
z{K%*};eJcw87m;L@O<lfA?ax)hFPD>x_fXATv`8m+@*Z4xNr`IXOZ^5U#Vq~aggtL
|
||||
zpj~`V8}OuQZC#*ypt@f4c68emktTjn79)H4+lyF=aT)U6QSKk=o<z|<#Pt(u*yo-x
|
||||
Sz5noP068fo$r^E^;Qs?Ck;k(D
|
||||
|
||||
literal 14310
|
||||
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%0ABLt+m?son?j
|
||||
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
|
||||
WX&3$!%>|s_1IbA#OV)^+1pg1OmmZn`
|
||||
|
||||
190
patches/server/0002-Leaf-Config.patch
Normal file
190
patches/server/0002-Leaf-Config.patch
Normal file
@@ -0,0 +1,190 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Wed, 12 Oct 2022 10:42:15 -0400
|
||||
Subject: [PATCH] Leaf Config
|
||||
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
index 2cc44fbf8e5bd436b6d4e19f6c06b351e750cb31..00f30e047beefe914543718009947ecc60c21790 100644
|
||||
--- a/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
@@ -242,7 +242,8 @@ public class TimingsExport extends Thread {
|
||||
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
|
||||
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
|
||||
pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Pufferfish
|
||||
- pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)) // Pufferfish
|
||||
+ pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)), // Pufferfish
|
||||
+ pair("leaf", mapAsJSON(org.dreeam.leaf.LeafConfig.getConfigCopy(), null)) // Leaf
|
||||
));
|
||||
|
||||
new TimingsExport(listeners, parent, history).start();
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index c69cb21f2ccf0f93a7ec17d4ee1ddb0ba5cfa5b2..3bed5eb755e97149a9651ca007564275e0eaf2d1 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1656,7 +1656,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@DontObfuscate
|
||||
public String getServerModName() {
|
||||
- return "Leaf"; // Leaf - Leaf > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
+ return org.dreeam.leaf.LeafConfig.serverModName; // Leaf - Leaf > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
|
||||
}
|
||||
|
||||
public SystemReport fillSystemReport(SystemReport details) {
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 673fb3955291407be37dc78be4eec9bf2018128b..a7023765e3c82e70574069af00227e3cf6f98e65 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -223,6 +223,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
// Paper end
|
||||
gg.pufferfish.pufferfish.PufferfishConfig.load(); // Pufferfish
|
||||
gg.pufferfish.pufferfish.PufferfishCommand.init(); // Pufferfish
|
||||
+ org.dreeam.leaf.LeafConfig.load(); // Leaf
|
||||
|
||||
this.setPvpAllowed(dedicatedserverproperties.pvp);
|
||||
this.setFlightAllowed(dedicatedserverproperties.allowFlight);
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..770553ef8976d76067396276792ea23a7ab7d51d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -0,0 +1,139 @@
|
||||
+package org.dreeam.leaf;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.configuration.ConfigurationSection;
|
||||
+import org.bukkit.configuration.MemoryConfiguration;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+import org.simpleyaml.configuration.comments.CommentType;
|
||||
+import org.simpleyaml.configuration.file.YamlFile;
|
||||
+import org.simpleyaml.exceptions.InvalidConfigurationException;
|
||||
+
|
||||
+import java.io.File;
|
||||
+import java.io.IOException;
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.util.List;
|
||||
+
|
||||
+public class LeafConfig {
|
||||
+
|
||||
+ private static final YamlFile config = new YamlFile();
|
||||
+ private static int updates = 0;
|
||||
+
|
||||
+ private static ConfigurationSection convertToBukkit(org.simpleyaml.configuration.ConfigurationSection section) {
|
||||
+ ConfigurationSection newSection = new MemoryConfiguration();
|
||||
+ for (String key : section.getKeys(false)) {
|
||||
+ if (section.isConfigurationSection(key)) {
|
||||
+ newSection.set(key, convertToBukkit(section.getConfigurationSection(key)));
|
||||
+ } else {
|
||||
+ newSection.set(key, section.get(key));
|
||||
+ }
|
||||
+ }
|
||||
+ return newSection;
|
||||
+ }
|
||||
+
|
||||
+ public static ConfigurationSection getConfigCopy() {
|
||||
+ return convertToBukkit(config);
|
||||
+ }
|
||||
+
|
||||
+ public static int getUpdates() {
|
||||
+ return updates;
|
||||
+ }
|
||||
+
|
||||
+ public static void load() throws IOException {
|
||||
+ File configFile = new File("leaf.yml");
|
||||
+
|
||||
+ if (configFile.exists()) {
|
||||
+ try {
|
||||
+ config.load(configFile);
|
||||
+ } catch (InvalidConfigurationException e) {
|
||||
+ throw new IOException(e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ getString("info.version", "1.0");
|
||||
+ setComment("info",
|
||||
+ "Leaf Config",
|
||||
+ "Github Repo: https://github.com/Dreeam-qwq/Leaf",
|
||||
+ "Discord: Dreeam#0851 | QQ: 2682173972");
|
||||
+
|
||||
+ for (Method method : LeafConfig.class.getDeclaredMethods()) {
|
||||
+ if (Modifier.isStatic(method.getModifiers()) && Modifier.isPrivate(method.getModifiers()) && method.getParameterCount() == 0 &&
|
||||
+ method.getReturnType() == Void.TYPE && !method.getName().startsWith("lambda")) {
|
||||
+ method.setAccessible(true);
|
||||
+ try {
|
||||
+ method.invoke(null);
|
||||
+ } catch (Throwable t) {
|
||||
+ MinecraftServer.LOGGER.warn("Failed to load configuration option from " + method.getName(), t);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ updates++;
|
||||
+
|
||||
+ config.save(configFile);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ private static void setComment(String key, String... comment) {
|
||||
+ if (config.contains(key)) {
|
||||
+ config.setComment(key, String.join("\n", comment), CommentType.BLOCK);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void ensureDefault(String key, Object defaultValue, String... comment) {
|
||||
+ if (!config.contains(key)) {
|
||||
+ config.set(key, defaultValue);
|
||||
+ config.setComment(key, String.join("\n", comment), CommentType.BLOCK);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static boolean getBoolean(String key, boolean defaultValue, String... comment) {
|
||||
+ return getBoolean(key, null, defaultValue, comment);
|
||||
+ }
|
||||
+
|
||||
+ private static boolean getBoolean(String key, @Nullable String oldKey, boolean defaultValue, String... comment) {
|
||||
+ ensureDefault(key, defaultValue, comment);
|
||||
+ return config.getBoolean(key, defaultValue);
|
||||
+ }
|
||||
+
|
||||
+ private static int getInt(String key, int defaultValue, String... comment) {
|
||||
+ return getInt(key, null, defaultValue, comment);
|
||||
+ }
|
||||
+
|
||||
+ private static int getInt(String key, @Nullable String oldKey, int defaultValue, String... comment) {
|
||||
+ ensureDefault(key, defaultValue, comment);
|
||||
+ return config.getInt(key, defaultValue);
|
||||
+ }
|
||||
+
|
||||
+ private static double getDouble(String key, double defaultValue, String... comment) {
|
||||
+ return getDouble(key, null, defaultValue, comment);
|
||||
+ }
|
||||
+
|
||||
+ private static double getDouble(String key, @Nullable String oldKey, double defaultValue, String... comment) {
|
||||
+ ensureDefault(key, defaultValue, comment);
|
||||
+ return config.getDouble(key, defaultValue);
|
||||
+ }
|
||||
+
|
||||
+ private static String getString(String key, String defaultValue, String... comment) {
|
||||
+ return getOldString(key, null, defaultValue, comment);
|
||||
+ }
|
||||
+
|
||||
+ private static String getOldString(String key, @Nullable String oldKey, String defaultValue, String... comment) {
|
||||
+ ensureDefault(key, defaultValue, comment);
|
||||
+ return config.getString(key, defaultValue);
|
||||
+ }
|
||||
+
|
||||
+ private static List<String> getStringList(String key, List<String> defaultValue, String... comment) {
|
||||
+ return getStringList(key, null, defaultValue, comment);
|
||||
+ }
|
||||
+
|
||||
+ private static List<String> getStringList(String key, @Nullable String oldKey, List<String> defaultValue, String... comment) {
|
||||
+ ensureDefault(key, defaultValue, comment);
|
||||
+ return config.getStringList(key);
|
||||
+ }
|
||||
+
|
||||
+ public static String serverModName = "Leaf";
|
||||
+ private static void serverModName() {
|
||||
+ serverModName = getString("settings.server-mod-name", serverModName);
|
||||
+ }
|
||||
+}
|
||||
73
patches/server/0003-Bump-Dependencies.patch
Normal file
73
patches/server/0003-Bump-Dependencies.patch
Normal file
@@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Fri, 28 Oct 2022 17:48:45 -0400
|
||||
Subject: [PATCH] Bump Dependencies
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index c8f031712006d95c59027791be1bdcdc2bd836c4..99c0750dcc87f5f3b19c5e9e4e9067d49443732e 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -22,13 +22,13 @@ dependencies {
|
||||
all its classes to check if they are plugins.
|
||||
Scanning takes about 1-2 seconds so adding this speeds up the server start.
|
||||
*/
|
||||
- implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation
|
||||
- annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for our Log4j plugins
|
||||
- implementation("io.netty:netty-codec-haproxy:4.1.77.Final") // Paper - Add support for proxy protocol
|
||||
+ implementation("org.apache.logging.log4j:log4j-core:2.19.0") // Paper - implementation
|
||||
+ annotationProcessor("org.apache.logging.log4j:log4j-core:2.19.0") // Paper - Needed to generate meta for our Log4j plugins
|
||||
+ implementation("io.netty:netty-codec-haproxy:4.1.85.Final") // Paper - Add support for proxy protocol
|
||||
// Paper end
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:2.19.0") // Paper - remove exclusion
|
||||
- implementation("org.ow2.asm:asm:9.3")
|
||||
- implementation("org.ow2.asm:asm-commons:9.3") // Paper - ASM event executor generation
|
||||
+ implementation("org.ow2.asm:asm:9.4")
|
||||
+ implementation("org.ow2.asm:asm-commons:9.4") // Paper - ASM event executor generation
|
||||
implementation("org.spongepowered:configurate-yaml:4.1.2") // Paper - config files
|
||||
implementation("commons-lang:commons-lang:2.6")
|
||||
implementation("net.fabricmc:mapping-io:0.3.0") // Paper - needed to read mappings for stacktrace deobfuscation
|
||||
@@ -37,27 +37,27 @@ dependencies {
|
||||
isTransitive = false
|
||||
}
|
||||
// Paper end
|
||||
- runtimeOnly("org.xerial:sqlite-jdbc:3.36.0.3")
|
||||
- runtimeOnly("mysql:mysql-connector-java:8.0.29")
|
||||
+ runtimeOnly("org.xerial:sqlite-jdbc:3.40.0.0")
|
||||
+ runtimeOnly("mysql:mysql-connector-java:8.0.30")
|
||||
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
||||
|
||||
runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.5")
|
||||
- runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
|
||||
- runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3")
|
||||
+ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.2")
|
||||
+ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.2")
|
||||
|
||||
// Pufferfish start
|
||||
- implementation("org.yaml:snakeyaml:1.32")
|
||||
- implementation ("me.carleslc.Simple-YAML:Simple-Yaml:1.8.2") {
|
||||
+ implementation("org.yaml:snakeyaml:1.33")
|
||||
+ implementation ("me.carleslc.Simple-YAML:Simple-Yaml:1.8.3") {
|
||||
exclude(group="org.yaml", module="snakeyaml")
|
||||
}
|
||||
// Pufferfish end
|
||||
implementation("com.github.technove:Flare:34637f3f87") // Pufferfish - flare
|
||||
|
||||
- testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
|
||||
+ testImplementation("io.github.classgraph:classgraph:4.8.152") // Paper - mob goal test
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
- testImplementation("org.hamcrest:hamcrest-library:1.3")
|
||||
+ testImplementation("org.hamcrest:hamcrest-library:2.2")
|
||||
|
||||
- implementation("io.netty:netty-all:4.1.77.Final"); // Paper - Bump netty
|
||||
+ implementation("io.netty:netty-all:4.1.85.Final"); // Paper - Bump netty
|
||||
}
|
||||
|
||||
val craftbukkitPackageVersion = "1_19_R2" // Paper
|
||||
@@ -206,3 +206,6 @@ tasks.registerRunTask("runDev") {
|
||||
description = "Spin up a non-relocated Mojang-mapped test server"
|
||||
classpath(sourceSets.main.map { it.runtimeClasspath })
|
||||
}
|
||||
+repositories {
|
||||
+ mavenCentral()
|
||||
+}
|
||||
49
patches/server/0004-Remove-Mojang-username-check.patch
Normal file
49
patches/server/0004-Remove-Mojang-username-check.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Wed, 12 Oct 2022 14:36:58 -0400
|
||||
Subject: [PATCH] Remove Mojang username check
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index f3b340fc6be9878d677a76673450aac3e0b73d4b..3011018c8fa221f515cf670dea9791f8c4ea1f69 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -36,6 +36,7 @@ import net.minecraft.util.Crypt;
|
||||
import net.minecraft.util.CryptException;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -237,7 +238,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@Override
|
||||
public void handleHello(ServerboundHelloPacket packet) {
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
|
||||
- Validate.validState(ServerLoginPacketListenerImpl.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]);
|
||||
+ if (!LeafConfig.removeMojangUsernameCheck) Validate.validState(ServerLoginPacketListenerImpl.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); // Leaf - Remove Mojang's username check
|
||||
// Paper start - validate usernames
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation) {
|
||||
if (!this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation && !validateUsername(packet.name())) {
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 770553ef8976d76067396276792ea23a7ab7d51d..7870c85030144831936d692dde4fff7bedd692da 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -132,8 +132,17 @@ public class LeafConfig {
|
||||
return config.getStringList(key);
|
||||
}
|
||||
|
||||
+
|
||||
public static String serverModName = "Leaf";
|
||||
private static void serverModName() {
|
||||
serverModName = getString("settings.server-mod-name", serverModName);
|
||||
}
|
||||
+
|
||||
+ public static boolean removeMojangUsernameCheck;
|
||||
+ private static void removeconfig() {
|
||||
+ removeMojangUsernameCheck = getBoolean("remove-Mojang-username-check", true,
|
||||
+ "Remove username check of Mojang",
|
||||
+ "enabling all characters as username");
|
||||
+
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Wed, 12 Oct 2022 14:48:45 -0400
|
||||
Subject: [PATCH] Remove Spigot Check for Broken BungeeCord Configurations
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
index e7ff7ad3bf4dd17fdd34202ec3aef8e9512bc36d..a00c7ba6d2161ce91ade78e3d53c8d57f86e9c99 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java
|
||||
@@ -9,6 +9,7 @@ import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
|
||||
import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener;
|
||||
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
|
||||
// CraftBukkit start
|
||||
import java.net.InetAddress;
|
||||
@@ -139,7 +140,9 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL
|
||||
{
|
||||
connection.spoofedProfile = ServerHandshakePacketListenerImpl.gson.fromJson(split[3], com.mojang.authlib.properties.Property[].class);
|
||||
}
|
||||
- } else if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) {
|
||||
+ // Leaf start - Remove Spigot check for broken BungeeCord configurations
|
||||
+ } else if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) && !(LeafConfig.removeSpigotCheckBungeeConfig)) {
|
||||
+ // Leaf end - Remove Spigot check for broken BungeeCord configurations
|
||||
Component chatmessage = Component.literal("Unknown data in login hostname, did you forget to enable BungeeCord in spigot.yml?");
|
||||
this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
|
||||
this.connection.disconnect(chatmessage);
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 7870c85030144831936d692dde4fff7bedd692da..c107a0cab333b2b57931862073a4eb6832f755ab 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -132,17 +132,19 @@ public class LeafConfig {
|
||||
return config.getStringList(key);
|
||||
}
|
||||
|
||||
-
|
||||
public static String serverModName = "Leaf";
|
||||
private static void serverModName() {
|
||||
serverModName = getString("settings.server-mod-name", serverModName);
|
||||
}
|
||||
|
||||
public static boolean removeMojangUsernameCheck;
|
||||
+ public static boolean removeSpigotCheckBungeeConfig;
|
||||
private static void removeconfig() {
|
||||
removeMojangUsernameCheck = getBoolean("remove-Mojang-username-check", true,
|
||||
"Remove username check of Mojang",
|
||||
"enabling all characters as username");
|
||||
-
|
||||
+ removeSpigotCheckBungeeConfig = getBoolean("remove-Spigot-check-bungee-config", true,
|
||||
+ "Enable player enter backend server through proxy",
|
||||
+ "without backend server enabling its bungee mode");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Sun, 6 Nov 2022 04:32:27 -0500
|
||||
Subject: [PATCH] Remove Paper's Fix tripwire state inconsistency
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
|
||||
index 7f60175bf671d282c11e9084670d2bb900968255..4e2fb4ee8e46b3c363992ff23e26f5a648c5f003 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
|
||||
@@ -74,7 +74,7 @@ public class TripWireBlock extends Block {
|
||||
@Override
|
||||
public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
|
||||
if (!moved && !state.is(newState.getBlock())) {
|
||||
- this.updateSource(world, pos, (BlockState) state.setValue(TripWireBlock.POWERED, true), true); // Paper - fix state inconsistency
|
||||
+ this.updateSource(world, pos, (BlockState) state.setValue(TripWireBlock.POWERED, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,12 +89,6 @@ public class TripWireBlock extends Block {
|
||||
}
|
||||
|
||||
private void updateSource(Level world, BlockPos pos, BlockState state) {
|
||||
- // Paper start - fix state inconsistency
|
||||
- this.updateSource(world, pos, state, false);
|
||||
- }
|
||||
-
|
||||
- private void updateSource(Level world, BlockPos pos, BlockState state, boolean beingRemoved) {
|
||||
- // Paper end
|
||||
Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST};
|
||||
int i = aenumdirection.length;
|
||||
int j = 0;
|
||||
@@ -110,7 +104,7 @@ public class TripWireBlock extends Block {
|
||||
|
||||
if (iblockdata1.is((Block) this.hook)) {
|
||||
if (iblockdata1.getValue(TripWireHookBlock.FACING) == enumdirection.getOpposite()) {
|
||||
- this.hook.calculateState(world, blockposition1, iblockdata1, false, true, k, state, beingRemoved); // Paper - fix state inconsistency
|
||||
+ this.hook.calculateState(world, blockposition1, iblockdata1, false, true, k, state);
|
||||
}
|
||||
} else if (iblockdata1.is((Block) this)) {
|
||||
++k;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index 004dce26ff073f1de52a84cd425c4f60fdab5e50..4a516828e5c6abd63511ee7c93fcff11203cf8d0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -108,12 +108,6 @@ public class TripWireHookBlock extends Block {
|
||||
}
|
||||
|
||||
public void calculateState(Level world, BlockPos pos, BlockState state, boolean beingRemoved, boolean flag1, int i, @Nullable BlockState iblockdata1) {
|
||||
- // Paper start - fix tripwire inconsistency
|
||||
- this.calculateState(world, pos, state, beingRemoved, flag1, i, iblockdata1, false);
|
||||
- }
|
||||
-
|
||||
- public void calculateState(Level world, BlockPos pos, BlockState state, boolean beingRemoved, boolean flag1, int i, @Nullable BlockState iblockdata1, boolean tripWireBeingRemoved) {
|
||||
- // Paper end
|
||||
Direction enumdirection = (Direction) state.getValue(TripWireHookBlock.FACING);
|
||||
boolean flag2 = (Boolean) state.getValue(TripWireHookBlock.ATTACHED);
|
||||
boolean flag3 = (Boolean) state.getValue(TripWireHookBlock.POWERED);
|
||||
@@ -147,7 +141,6 @@ public class TripWireHookBlock extends Block {
|
||||
boolean flag7 = (Boolean) iblockdata2.getValue(TripWireBlock.POWERED);
|
||||
|
||||
flag5 |= flag6 && flag7;
|
||||
- if (k != i || !tripWireBeingRemoved || !flag6) // Paper - don't update the tripwire again if being removed and not disarmed
|
||||
aiblockdata[k] = iblockdata2;
|
||||
if (k == i) {
|
||||
world.scheduleTick(pos, (Block) this, 10);
|
||||
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Fri, 18 Nov 2022 23:26:16 -0500
|
||||
Subject: [PATCH] Remove UseItemOnPacket Too Far Check
|
||||
|
||||
This Check is added in 1.17.x -> 1.18.x update by Mojang.
|
||||
By removing this check, it enable hackers to use some modules of hack clients.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index aa23559719357f2678e3aa759d58ba4bde18bdd4..215eda414547bfdf662b4ea511fa3f774e125d94 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -182,6 +182,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.BooleanOp;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -1952,7 +1953,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
Vec3 vec3d2 = vec3d.subtract(vec3d1);
|
||||
double d0 = 1.0000001D;
|
||||
|
||||
- if (Math.abs(vec3d2.x()) < 1.0000001D && Math.abs(vec3d2.y()) < 1.0000001D && Math.abs(vec3d2.z()) < 1.0000001D) {
|
||||
+ if ((Math.abs(vec3d2.x()) < 1.0000001D && Math.abs(vec3d2.y()) < 1.0000001D && Math.abs(vec3d2.z()) < 1.0000001D) || LeafConfig.removeUseItemOnPacketTooFar) { // Leaf - Remove UseItemOnPacket Too Far Check
|
||||
Direction enumdirection = movingobjectpositionblock.getDirection();
|
||||
|
||||
this.player.resetLastActionTime();
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index c107a0cab333b2b57931862073a4eb6832f755ab..a221affdf87d28991248a4b83224194e222423e6 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -139,6 +139,8 @@ public class LeafConfig {
|
||||
|
||||
public static boolean removeMojangUsernameCheck;
|
||||
public static boolean removeSpigotCheckBungeeConfig;
|
||||
+ public static boolean removeUseItemOnPacketTooFar;
|
||||
+
|
||||
private static void removeconfig() {
|
||||
removeMojangUsernameCheck = getBoolean("remove-Mojang-username-check", true,
|
||||
"Remove username check of Mojang",
|
||||
@@ -146,5 +148,7 @@ public class LeafConfig {
|
||||
removeSpigotCheckBungeeConfig = getBoolean("remove-Spigot-check-bungee-config", true,
|
||||
"Enable player enter backend server through proxy",
|
||||
"without backend server enabling its bungee mode");
|
||||
+ removeUseItemOnPacketTooFar = getBoolean("remove-UseItemOnPacket-too-far-check", false,
|
||||
+ "To enable this, players can use some packet modules with hack clients");
|
||||
}
|
||||
}
|
||||
548
patches/server/0008-Purpur-Implement-TPSBar.patch
Normal file
548
patches/server/0008-Purpur-Implement-TPSBar.patch
Normal file
@@ -0,0 +1,548 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sat, 12 Dec 2020 21:19:05 -0600
|
||||
Subject: [PATCH] Purpur: Implement TPSBar
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java
|
||||
index 39844531b03eb8a6c70700b4ecbf0ff1a557424d..632ae75cb3bbc7a3955872d14ad0fbc2459f32e8 100644
|
||||
--- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java
|
||||
+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java
|
||||
@@ -35,6 +35,7 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
|
||||
private final boolean forks;
|
||||
private Command<S> command;
|
||||
public LiteralCommandNode<CommandSourceStack> clientNode = null; // Paper
|
||||
+ private String permission = null; public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission; } // Purpur
|
||||
// CraftBukkit start
|
||||
public void removeCommand(String name) {
|
||||
this.children.remove(name);
|
||||
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
index ae5dd08de75a7ed231295f306fd0974da3988249..b8d49f7607c646216d42f4e047997d47b49f228f 100644
|
||||
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -317,6 +317,30 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
|
||||
}
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public void sendSuccess(@Nullable String message) {
|
||||
+ sendSuccess(message, false);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable String message, boolean broadcastToOps) {
|
||||
+ if (message == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ sendSuccess(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message), broadcastToOps);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ sendSuccess(message, false);
|
||||
+ }
|
||||
+
|
||||
+ public void sendSuccess(@Nullable net.kyori.adventure.text.Component message, boolean broadcastToOps) {
|
||||
+ if (message == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), broadcastToOps);
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
public void sendSuccess(Component message, boolean broadcastToOps) {
|
||||
if (this.source.acceptsSuccess() && !this.silent) {
|
||||
this.source.sendSystemMessage(message);
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index 330f6c79417378da855326b4da665f9d240e748d..564830a1d511716ab977923ba43fa38c475f484f 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -215,6 +215,7 @@ public class Commands {
|
||||
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
|
||||
StopCommand.register(this.dispatcher);
|
||||
WhitelistCommand.register(this.dispatcher);
|
||||
+ org.dreeam.leaf.commands.TPSBarCommand.register(this.dispatcher); // Purpur
|
||||
}
|
||||
|
||||
if (environment.includeIntegrated) {
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 3bed5eb755e97149a9651ca007564275e0eaf2d1..ab0a4a36241bee59b142df65736003c69dcb3dd4 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1022,6 +1022,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.safeShutdown(waitForShutdown, false);
|
||||
}
|
||||
public void safeShutdown(boolean waitForShutdown, boolean isRestarting) {
|
||||
+ org.dreeam.leaf.tasks.BossBarTask.stopAll(); // Purpur
|
||||
this.isRestarting = isRestarting;
|
||||
this.hasLoggedStop = true; // Paper
|
||||
if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index a7023765e3c82e70574069af00227e3cf6f98e65..598d0200c055ef357a0a0d8857ce740d0bff9bae 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -50,6 +50,7 @@ import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.block.entity.SkullBlockEntity;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
+import org.dreeam.leaf.tasks.BossBarTask;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -336,6 +337,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) mobSpawnExecutor.start(); // Pufferfish
|
||||
+ BossBarTask.startAll(); // Purpur
|
||||
return true;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index c0b0a7fdb75266a7064d54bda6441953184ecc64..3db273840ecc03e7bf3e1a01f56d5128e4aeea06 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -270,6 +270,7 @@ public class ServerPlayer extends Player {
|
||||
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
|
||||
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
||||
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
|
||||
+ private boolean tpsBar = false; // Purpur
|
||||
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
|
||||
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
|
||||
@@ -508,6 +509,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -574,6 +576,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
this.getBukkitEntity().setExtraData(nbt); // CraftBukkit
|
||||
|
||||
+ nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur
|
||||
}
|
||||
|
||||
// CraftBukkit start - World fallback code, either respawn location or global spawn
|
||||
@@ -2550,4 +2553,14 @@ public class ServerPlayer extends Player {
|
||||
return (CraftPlayer) super.getBukkitEntity();
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Purpur start
|
||||
+ public boolean tpsBar() {
|
||||
+ return this.tpsBar;
|
||||
+ }
|
||||
+
|
||||
+ public void tpsBar(boolean tpsBar) {
|
||||
+ this.tpsBar = tpsBar;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index b348d33726b2b14ea2d12ce3430df2c0b94295f4..1895a3919d43e8e4f8399c75db8482df9e78bb3d 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -100,6 +100,7 @@ import net.minecraft.world.scores.Objective;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.Scoreboard; // Paper
|
||||
import net.minecraft.world.scores.Team;
|
||||
+import org.dreeam.leaf.tasks.BossBarTask;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -511,6 +512,7 @@ public abstract class PlayerList {
|
||||
scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
|
||||
}
|
||||
// Paper end
|
||||
+ BossBarTask.addToAll(player); // Purpur
|
||||
// CraftBukkit - Moved from above, added world
|
||||
PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
|
||||
}
|
||||
@@ -621,6 +623,8 @@ public abstract class PlayerList {
|
||||
}
|
||||
public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer, net.kyori.adventure.text.Component leaveMessage) {
|
||||
// Paper end
|
||||
+ BossBarTask.removeFromAll(entityplayer.getBukkitEntity()); // Purpur
|
||||
+
|
||||
ServerLevel worldserver = entityplayer.getLevel();
|
||||
|
||||
entityplayer.awardStat(Stats.LEAVE_GAME);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
index 6035af2cf08353b3d3801220d8116d8611a0cd37..7774ab6a2e553a40def4bb4dceea9e5f58d31c1e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
|
||||
@@ -94,6 +94,7 @@ public final class VanillaCommandWrapper extends BukkitCommand {
|
||||
}
|
||||
|
||||
public static String getPermission(CommandNode<CommandSourceStack> vanillaCommand) {
|
||||
+ if (vanillaCommand.getPermission() != null) return vanillaCommand.getPermission(); // Purpur
|
||||
// Paper start
|
||||
final String commandName;
|
||||
if (vanillaCommand.getRedirect() == null) {
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index a221affdf87d28991248a4b83224194e222423e6..a0bd1ec3f09959c7f72b484658c1c94a16818281 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.dreeam.leaf;
|
||||
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
+import org.dreeam.leaf.tasks.TPSBarTask;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.simpleyaml.configuration.comments.CommentType;
|
||||
import org.simpleyaml.configuration.file.YamlFile;
|
||||
@@ -149,6 +151,36 @@ public class LeafConfig {
|
||||
"Enable player enter backend server through proxy",
|
||||
"without backend server enabling its bungee mode");
|
||||
removeUseItemOnPacketTooFar = getBoolean("remove-UseItemOnPacket-too-far-check", false,
|
||||
- "To enable this, players can use some packet modules with hack clients");
|
||||
+ "To enable this, players can use some packet modules with hack clients");
|
||||
+ }
|
||||
+
|
||||
+ public static String tpsbarCommandOutput = "<green>Tpsbar toggled <onoff> for <target>";
|
||||
+
|
||||
+ private static void messages() {
|
||||
+ tpsbarCommandOutput = getString("settings.messages.tpsbar-command-output", tpsbarCommandOutput);
|
||||
+ }
|
||||
+
|
||||
+ public static String commandTPSBarTitle = "<gray>TPS<yellow>:</yellow> <tps> MSPT<yellow>:</yellow> <mspt> Ping<yellow>:</yellow> <ping>ms";
|
||||
+ public static BossBar.Overlay commandTPSBarProgressOverlay = BossBar.Overlay.NOTCHED_20;
|
||||
+ public static TPSBarTask.FillMode commandTPSBarProgressFillMode = TPSBarTask.FillMode.MSPT;
|
||||
+ public static BossBar.Color commandTPSBarProgressColorGood = BossBar.Color.GREEN;
|
||||
+ public static BossBar.Color commandTPSBarProgressColorMedium = BossBar.Color.YELLOW;
|
||||
+ public static BossBar.Color commandTPSBarProgressColorLow = BossBar.Color.RED;
|
||||
+ public static String commandTPSBarTextColorGood = "<gradient:#55ff55:#00aa00><text></gradient>";
|
||||
+ public static String commandTPSBarTextColorMedium = "<gradient:#ffff55:#ffaa00><text></gradient>";
|
||||
+ public static String commandTPSBarTextColorLow = "<gradient:#ff5555:#aa0000><text></gradient>";
|
||||
+ public static int commandTPSBarTickInterval = 20;
|
||||
+
|
||||
+ private static void commandSettings() {
|
||||
+ commandTPSBarTitle = getString("settings.command.tpsbar.title", commandTPSBarTitle);
|
||||
+ commandTPSBarProgressOverlay = BossBar.Overlay.valueOf(getString("settings.command.tpsbar.overlay", commandTPSBarProgressOverlay.name()));
|
||||
+ commandTPSBarProgressFillMode = TPSBarTask.FillMode.valueOf(getString("settings.command.tpsbar.fill-mode", commandTPSBarProgressFillMode.name()));
|
||||
+ commandTPSBarProgressColorGood = BossBar.Color.valueOf(getString("settings.command.tpsbar.progress-color.good", commandTPSBarProgressColorGood.name()));
|
||||
+ commandTPSBarProgressColorMedium = BossBar.Color.valueOf(getString("settings.command.tpsbar.progress-color.medium", commandTPSBarProgressColorMedium.name()));
|
||||
+ commandTPSBarProgressColorLow = BossBar.Color.valueOf(getString("settings.command.tpsbar.progress-color.low", commandTPSBarProgressColorLow.name()));
|
||||
+ commandTPSBarTextColorGood = getString("settings.command.tpsbar.text-color.good", commandTPSBarTextColorGood);
|
||||
+ commandTPSBarTextColorMedium = getString("settings.command.tpsbar.text-color.medium", commandTPSBarTextColorMedium);
|
||||
+ commandTPSBarTextColorLow = getString("settings.command.tpsbar.text-color.low", commandTPSBarTextColorLow);
|
||||
+ commandTPSBarTickInterval = getInt("settings.command.tpsbar.tick-interval", commandTPSBarTickInterval);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/commands/TPSBarCommand.java b/src/main/java/org/dreeam/leaf/commands/TPSBarCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..60742c5ecc99aa18d7292bd6df5e80441b19745b
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/commands/TPSBarCommand.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package org.dreeam.leaf.commands;
|
||||
+
|
||||
+import com.mojang.brigadier.CommandDispatcher;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.commands.Commands;
|
||||
+import net.minecraft.commands.arguments.EntityArgument;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+import org.dreeam.leaf.tasks.TPSBarTask;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.Collections;
|
||||
+
|
||||
+public class TPSBarCommand {
|
||||
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+ dispatcher.register(Commands.literal("tpsbar")
|
||||
+ .requires(listener -> listener.hasPermission(2))
|
||||
+ .executes(context -> execute(context.getSource(), Collections.singleton(context.getSource().getPlayerOrException())))
|
||||
+ .then(Commands.argument("targets", EntityArgument.players())
|
||||
+ .executes((context) -> execute(context.getSource(), EntityArgument.getPlayers(context, "targets")))
|
||||
+ )
|
||||
+ ).setPermission("bukkit.command.tpsbar");
|
||||
+ }
|
||||
+
|
||||
+ private static int execute(CommandSourceStack sender, Collection<ServerPlayer> targets) {
|
||||
+ for (ServerPlayer player : targets) {
|
||||
+ boolean result = TPSBarTask.instance().togglePlayer(player.getBukkitEntity());
|
||||
+ player.tpsBar(result);
|
||||
+
|
||||
+ Component output = MiniMessage.miniMessage().deserialize(LeafConfig.tpsbarCommandOutput,
|
||||
+ Placeholder.component("onoff", Component.translatable(result ? "options.on" : "options.off")
|
||||
+ .color(result ? NamedTextColor.GREEN : NamedTextColor.RED)),
|
||||
+ Placeholder.parsed("target", player.getGameProfile().getName()));
|
||||
+
|
||||
+ sender.sendSuccess(output, false);
|
||||
+ }
|
||||
+ return targets.size();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ae629c689779339589de3ec28fb6a79bf54da583
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
@@ -0,0 +1,109 @@
|
||||
+package org.dreeam.leaf.tasks;
|
||||
+
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.craftbukkit.scheduler.MinecraftInternalPlugin;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.scheduler.BukkitRunnable;
|
||||
+
|
||||
+import java.util.HashMap;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.Map;
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+public abstract class BossBarTask extends BukkitRunnable {
|
||||
+ private final Map<UUID, BossBar> bossbars = new HashMap<>();
|
||||
+ private boolean started;
|
||||
+
|
||||
+ abstract BossBar createBossBar();
|
||||
+
|
||||
+ abstract void updateBossBar(BossBar bossbar, Player player);
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ Iterator<Map.Entry<UUID, BossBar>> iter = bossbars.entrySet().iterator();
|
||||
+ while (iter.hasNext()) {
|
||||
+ Map.Entry<UUID, BossBar> entry = iter.next();
|
||||
+ Player player = Bukkit.getPlayer(entry.getKey());
|
||||
+ if (player == null) {
|
||||
+ iter.remove();
|
||||
+ continue;
|
||||
+ }
|
||||
+ updateBossBar(entry.getValue(), player);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void cancel() {
|
||||
+ super.cancel();
|
||||
+ new HashSet<>(this.bossbars.keySet()).forEach(uuid -> {
|
||||
+ Player player = Bukkit.getPlayer(uuid);
|
||||
+ if (player != null) {
|
||||
+ removePlayer(player);
|
||||
+ }
|
||||
+ });
|
||||
+ this.bossbars.clear();
|
||||
+ }
|
||||
+
|
||||
+ public boolean removePlayer(Player player) {
|
||||
+ BossBar bossbar = this.bossbars.remove(player.getUniqueId());
|
||||
+ if (bossbar != null) {
|
||||
+ player.hideBossBar(bossbar);
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public void addPlayer(Player player) {
|
||||
+ removePlayer(player);
|
||||
+ BossBar bossbar = createBossBar();
|
||||
+ this.bossbars.put(player.getUniqueId(), bossbar);
|
||||
+ this.updateBossBar(bossbar, player);
|
||||
+ player.showBossBar(bossbar);
|
||||
+ }
|
||||
+
|
||||
+ public boolean hasPlayer(UUID uuid) {
|
||||
+ return this.bossbars.containsKey(uuid);
|
||||
+ }
|
||||
+
|
||||
+ public boolean togglePlayer(Player player) {
|
||||
+ if (removePlayer(player)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ addPlayer(player);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public void start() {
|
||||
+ stop();
|
||||
+ this.runTaskTimerAsynchronously(new MinecraftInternalPlugin(), 1, 1);
|
||||
+ started = true;
|
||||
+ }
|
||||
+
|
||||
+ public void stop() {
|
||||
+ if (started) {
|
||||
+ cancel();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void startAll() {
|
||||
+ TPSBarTask.instance().start();
|
||||
+ }
|
||||
+
|
||||
+ public static void stopAll() {
|
||||
+ TPSBarTask.instance().stop();
|
||||
+ }
|
||||
+
|
||||
+ public static void addToAll(ServerPlayer player) {
|
||||
+ Player bukkit = player.getBukkitEntity();
|
||||
+ if (player.tpsBar()) {
|
||||
+ TPSBarTask.instance().addPlayer(bukkit);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void removeFromAll(Player player) {
|
||||
+ TPSBarTask.instance().removePlayer(player);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/TPSBarTask.java b/src/main/java/org/dreeam/leaf/tasks/TPSBarTask.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9a184179d5968691a9c50be5536a7ce6b6c51dd0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/TPSBarTask.java
|
||||
@@ -0,0 +1,142 @@
|
||||
+package org.dreeam.leaf.tasks;
|
||||
+
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.entity.Player;
|
||||
+
|
||||
+public class TPSBarTask extends BossBarTask {
|
||||
+ private static TPSBarTask instance;
|
||||
+ private double tps = 20.0D;
|
||||
+ private double mspt = 0.0D;
|
||||
+ private int tick = 0;
|
||||
+
|
||||
+ public static TPSBarTask instance() {
|
||||
+ if (instance == null) {
|
||||
+ instance = new TPSBarTask();
|
||||
+ }
|
||||
+ return instance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ BossBar createBossBar() {
|
||||
+ return BossBar.bossBar(Component.text(""), 0.0F, instance().getBossBarColor(), LeafConfig.commandTPSBarProgressOverlay);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ void updateBossBar(BossBar bossbar, Player player) {
|
||||
+ bossbar.progress(getBossBarProgress());
|
||||
+ bossbar.color(getBossBarColor());
|
||||
+ bossbar.name(MiniMessage.miniMessage().deserialize(LeafConfig.commandTPSBarTitle,
|
||||
+ Placeholder.component("tps", getTPSColor()),
|
||||
+ Placeholder.component("mspt", getMSPTColor()),
|
||||
+ Placeholder.component("ping", getPingColor(player.getPing()))
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ if (++tick < LeafConfig.commandTPSBarTickInterval) {
|
||||
+ return;
|
||||
+ }
|
||||
+ tick = 0;
|
||||
+
|
||||
+ this.tps = Math.max(Math.min(Bukkit.getTPS()[0], 20.0D), 0.0D);
|
||||
+ this.mspt = Bukkit.getAverageTickTime();
|
||||
+
|
||||
+ super.run();
|
||||
+ }
|
||||
+
|
||||
+ private float getBossBarProgress() {
|
||||
+ if (LeafConfig.commandTPSBarProgressFillMode == FillMode.MSPT) {
|
||||
+ return Math.max(Math.min((float) mspt / 50.0F, 1.0F), 0.0F);
|
||||
+ } else {
|
||||
+ return Math.max(Math.min((float) tps / 20.0F, 1.0F), 0.0F);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private BossBar.Color getBossBarColor() {
|
||||
+ if (isGood(LeafConfig.commandTPSBarProgressFillMode)) {
|
||||
+ return LeafConfig.commandTPSBarProgressColorGood;
|
||||
+ } else if (isMedium(LeafConfig.commandTPSBarProgressFillMode)) {
|
||||
+ return LeafConfig.commandTPSBarProgressColorMedium;
|
||||
+ } else {
|
||||
+ return LeafConfig.commandTPSBarProgressColorLow;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private boolean isGood(FillMode mode) {
|
||||
+ return isGood(mode, 0);
|
||||
+ }
|
||||
+
|
||||
+ private boolean isGood(FillMode mode, int ping) {
|
||||
+ if (mode == FillMode.MSPT) {
|
||||
+ return mspt < 40;
|
||||
+ } else if (mode == FillMode.TPS) {
|
||||
+ return tps >= 19;
|
||||
+ } else if (mode == FillMode.PING) {
|
||||
+ return ping < 100;
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private boolean isMedium(FillMode mode) {
|
||||
+ return isMedium(mode, 0);
|
||||
+ }
|
||||
+
|
||||
+ private boolean isMedium(FillMode mode, int ping) {
|
||||
+ if (mode == FillMode.MSPT) {
|
||||
+ return mspt < 50;
|
||||
+ } else if (mode == FillMode.TPS) {
|
||||
+ return tps >= 15;
|
||||
+ } else if (mode == FillMode.PING) {
|
||||
+ return ping < 200;
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Component getTPSColor() {
|
||||
+ String color;
|
||||
+ if (isGood(FillMode.TPS)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorGood;
|
||||
+ } else if (isMedium(FillMode.TPS)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorMedium;
|
||||
+ } else {
|
||||
+ color = LeafConfig.commandTPSBarTextColorLow;
|
||||
+ }
|
||||
+ return MiniMessage.miniMessage().deserialize(color, Placeholder.parsed("text", String.format("%.2f", tps)));
|
||||
+ }
|
||||
+
|
||||
+ private Component getMSPTColor() {
|
||||
+ String color;
|
||||
+ if (isGood(FillMode.MSPT)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorGood;
|
||||
+ } else if (isMedium(FillMode.MSPT)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorMedium;
|
||||
+ } else {
|
||||
+ color = LeafConfig.commandTPSBarTextColorLow;
|
||||
+ }
|
||||
+ return MiniMessage.miniMessage().deserialize(color, Placeholder.parsed("text", String.format("%.2f", mspt)));
|
||||
+ }
|
||||
+
|
||||
+ private Component getPingColor(int ping) {
|
||||
+ String color;
|
||||
+ if (isGood(FillMode.PING, ping)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorGood;
|
||||
+ } else if (isMedium(FillMode.PING, ping)) {
|
||||
+ color = LeafConfig.commandTPSBarTextColorMedium;
|
||||
+ } else {
|
||||
+ color = LeafConfig.commandTPSBarTextColorLow;
|
||||
+ }
|
||||
+ return MiniMessage.miniMessage().deserialize(color, Placeholder.parsed("text", String.format("%s", ping)));
|
||||
+ }
|
||||
+
|
||||
+ public enum FillMode {
|
||||
+ TPS, MSPT, PING
|
||||
+ }
|
||||
+}
|
||||
234
patches/server/0009-Purpur-Add-compass-command.patch
Normal file
234
patches/server/0009-Purpur-Add-compass-command.patch
Normal file
@@ -0,0 +1,234 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 24 Jul 2021 00:07:31 -0500
|
||||
Subject: [PATCH] Purpur: Add compass command
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index 564830a1d511716ab977923ba43fa38c475f484f..2c5afab3cc0c66a2e63c1f647a033ca1a58f9e39 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -216,6 +216,7 @@ public class Commands {
|
||||
StopCommand.register(this.dispatcher);
|
||||
WhitelistCommand.register(this.dispatcher);
|
||||
org.dreeam.leaf.commands.TPSBarCommand.register(this.dispatcher); // Purpur
|
||||
+ org.dreeam.leaf.commands.CompassCommand.register(this.dispatcher); // Purpur
|
||||
}
|
||||
|
||||
if (environment.includeIntegrated) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3db273840ecc03e7bf3e1a01f56d5128e4aeea06..5c67d38df288e789597613df99f779c1ddf40712 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -271,6 +271,7 @@ public class ServerPlayer extends Player {
|
||||
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
|
||||
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
|
||||
private boolean tpsBar = false; // Purpur
|
||||
+ private boolean compassBar = false; // Purpur
|
||||
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
|
||||
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
|
||||
@@ -510,6 +511,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
|
||||
if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur
|
||||
+ if (nbt.contains("Purpur.CompassBar")) { this.compassBar = nbt.getBoolean("Purpur.CompassBar"); } // Purpur
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -577,6 +579,7 @@ public class ServerPlayer extends Player {
|
||||
this.getBukkitEntity().setExtraData(nbt); // CraftBukkit
|
||||
|
||||
nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur
|
||||
+ nbt.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur
|
||||
}
|
||||
|
||||
// CraftBukkit start - World fallback code, either respawn location or global spawn
|
||||
@@ -2562,5 +2565,13 @@ public class ServerPlayer extends Player {
|
||||
public void tpsBar(boolean tpsBar) {
|
||||
this.tpsBar = tpsBar;
|
||||
}
|
||||
+
|
||||
+ public boolean compassBar() {
|
||||
+ return this.compassBar;
|
||||
+ }
|
||||
+
|
||||
+ public void compassBar(boolean compassBar) {
|
||||
+ this.compassBar = compassBar;
|
||||
+ }
|
||||
// Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index a0bd1ec3f09959c7f72b484658c1c94a16818281..e56151fe0dbc0c867dff728a55daa35c7714d3a6 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -170,6 +170,11 @@ public class LeafConfig {
|
||||
public static String commandTPSBarTextColorMedium = "<gradient:#ffff55:#ffaa00><text></gradient>";
|
||||
public static String commandTPSBarTextColorLow = "<gradient:#ff5555:#aa0000><text></gradient>";
|
||||
public static int commandTPSBarTickInterval = 20;
|
||||
+ public static String commandCompassBarTitle = "S \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 SW \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 W \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 NW \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 N \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 NE \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 E \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 SE \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 S \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 SW \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 W \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 NW \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 N \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 NE \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 E \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 SE \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 \u25C8 \u00B7 ";
|
||||
+ public static BossBar.Overlay commandCompassBarProgressOverlay = BossBar.Overlay.PROGRESS;
|
||||
+ public static BossBar.Color commandCompassBarProgressColor = BossBar.Color.BLUE;
|
||||
+ public static float commandCompassBarProgressPercent = 1.0F;
|
||||
+ public static int commandCompassBarTickInterval = 5;
|
||||
|
||||
private static void commandSettings() {
|
||||
commandTPSBarTitle = getString("settings.command.tpsbar.title", commandTPSBarTitle);
|
||||
@@ -182,5 +187,17 @@ public class LeafConfig {
|
||||
commandTPSBarTextColorMedium = getString("settings.command.tpsbar.text-color.medium", commandTPSBarTextColorMedium);
|
||||
commandTPSBarTextColorLow = getString("settings.command.tpsbar.text-color.low", commandTPSBarTextColorLow);
|
||||
commandTPSBarTickInterval = getInt("settings.command.tpsbar.tick-interval", commandTPSBarTickInterval);
|
||||
+
|
||||
+ commandCompassBarTitle = getString("settings.command.compass.title", commandCompassBarTitle);
|
||||
+ commandCompassBarProgressOverlay = BossBar.Overlay.valueOf(getString("settings.command.compass.overlay", commandCompassBarProgressOverlay.name()));
|
||||
+ commandCompassBarProgressColor = BossBar.Color.valueOf(getString("settings.command.compass.progress-color", commandCompassBarProgressColor.name()));
|
||||
+ commandCompassBarProgressPercent = (float) getDouble("settings.command.compass.percent", commandCompassBarProgressPercent);
|
||||
+ commandCompassBarTickInterval = getInt("settings.command.compass.tick-interval", commandCompassBarTickInterval);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ public static boolean compassItemShowsBossBar = false;
|
||||
+ private static void itemSettings() {
|
||||
+ compassItemShowsBossBar = getBoolean("gameplay-mechanics.item.compass.holding-shows-bossbar", compassItemShowsBossBar);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/commands/CompassCommand.java b/src/main/java/org/dreeam/leaf/commands/CompassCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a3c85794307e906c4343d490e0e10daaab0efb38
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/commands/CompassCommand.java
|
||||
@@ -0,0 +1,27 @@
|
||||
+package org.dreeam.leaf.commands;
|
||||
+
|
||||
+import com.mojang.brigadier.CommandDispatcher;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.commands.Commands;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.dreeam.leaf.tasks.CompassTask;
|
||||
+
|
||||
+public class CompassCommand {
|
||||
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+ dispatcher.register(Commands.literal("compass")
|
||||
+ .requires(listener -> listener.hasPermission(2))
|
||||
+ .executes(context -> {
|
||||
+ ServerPlayer player = context.getSource().getPlayerOrException();
|
||||
+ CompassTask task = CompassTask.instance();
|
||||
+ if (player.compassBar()) {
|
||||
+ task.removePlayer(player.getBukkitEntity());
|
||||
+ player.compassBar(false);
|
||||
+ } else {
|
||||
+ task.addPlayer(player.getBukkitEntity());
|
||||
+ player.compassBar(true);
|
||||
+ }
|
||||
+ return 1;
|
||||
+ })
|
||||
+ ).setPermission("bukkit.command.compass");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
index ae629c689779339589de3ec28fb6a79bf54da583..7dacf4f21d082dd9a19db6e5122d06b5bda8fc95 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
@@ -90,10 +90,12 @@ public abstract class BossBarTask extends BukkitRunnable {
|
||||
|
||||
public static void startAll() {
|
||||
TPSBarTask.instance().start();
|
||||
+ CompassTask.instance().start();
|
||||
}
|
||||
|
||||
public static void stopAll() {
|
||||
TPSBarTask.instance().stop();
|
||||
+ CompassTask.instance().stop();
|
||||
}
|
||||
|
||||
public static void addToAll(ServerPlayer player) {
|
||||
@@ -101,9 +103,13 @@ public abstract class BossBarTask extends BukkitRunnable {
|
||||
if (player.tpsBar()) {
|
||||
TPSBarTask.instance().addPlayer(bukkit);
|
||||
}
|
||||
+ if (player.compassBar()) {
|
||||
+ CompassTask.instance().addPlayer(bukkit);
|
||||
+ }
|
||||
}
|
||||
|
||||
public static void removeFromAll(Player player) {
|
||||
TPSBarTask.instance().removePlayer(player);
|
||||
+ CompassTask.instance().removePlayer(player);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/CompassTask.java b/src/main/java/org/dreeam/leaf/tasks/CompassTask.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3ecd9bb435e5066176da88f7d50d4920cee017e5
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/CompassTask.java
|
||||
@@ -0,0 +1,68 @@
|
||||
+package org.dreeam.leaf.tasks;
|
||||
+
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.world.item.Items;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+
|
||||
+public class CompassTask extends BossBarTask {
|
||||
+ private static CompassTask instance;
|
||||
+
|
||||
+ private int tick = 0;
|
||||
+
|
||||
+ public static CompassTask instance() {
|
||||
+ if (instance == null) {
|
||||
+ instance = new CompassTask();
|
||||
+ }
|
||||
+ return instance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ if (++tick < LeafConfig.commandCompassBarTickInterval) {
|
||||
+ return;
|
||||
+ }
|
||||
+ tick = 0;
|
||||
+
|
||||
+ MinecraftServer.getServer().getAllLevels().forEach((level) -> {
|
||||
+ if (LeafConfig.compassItemShowsBossBar) {
|
||||
+ level.players().forEach(player -> {
|
||||
+ if (!player.compassBar()) {
|
||||
+ if (player.getMainHandItem().getItem() != Items.COMPASS && player.getOffhandItem().getItem() != Items.COMPASS) {
|
||||
+ removePlayer(player.getBukkitEntity());
|
||||
+ } else if (!hasPlayer(player.getUUID())) {
|
||||
+ addPlayer(player.getBukkitEntity());
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ super.run();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ BossBar createBossBar() {
|
||||
+ return BossBar.bossBar(Component.text(""), LeafConfig.commandCompassBarProgressPercent, LeafConfig.commandCompassBarProgressColor, LeafConfig.commandCompassBarProgressOverlay);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ void updateBossBar(BossBar bossbar, Player player) {
|
||||
+ float yaw = player.getLocation().getYaw();
|
||||
+ int length = LeafConfig.commandCompassBarTitle.length();
|
||||
+ int pos = (int) ((normalize(yaw) * (length / 720F)) + (length / 2F));
|
||||
+ bossbar.name(Component.text(LeafConfig.commandCompassBarTitle.substring(pos - 25, pos + 25)));
|
||||
+ }
|
||||
+
|
||||
+ private float normalize(float yaw) {
|
||||
+ while (yaw < -180.0F) {
|
||||
+ yaw += 360.0F;
|
||||
+ }
|
||||
+ while (yaw > 180.0F) {
|
||||
+ yaw -= 360.0F;
|
||||
+ }
|
||||
+ return yaw;
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1,345 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Mon, 26 Sep 2022 07:43:30 -0500
|
||||
Subject: [PATCH] Purpur: Implement ram and rambar commands
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index 2c5afab3cc0c66a2e63c1f647a033ca1a58f9e39..8ee8ff15f4511684261ff7a9417baa2ccd313b69 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -217,6 +217,8 @@ public class Commands {
|
||||
WhitelistCommand.register(this.dispatcher);
|
||||
org.dreeam.leaf.commands.TPSBarCommand.register(this.dispatcher); // Purpur
|
||||
org.dreeam.leaf.commands.CompassCommand.register(this.dispatcher); // Purpur
|
||||
+ org.dreeam.leaf.commands.RamBarCommand.register(this.dispatcher); // Purpur
|
||||
+ org.dreeam.leaf.commands.RamCommand.register(this.dispatcher); // Purpur
|
||||
}
|
||||
|
||||
if (environment.includeIntegrated) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 5c67d38df288e789597613df99f779c1ddf40712..95db6657cd65b71f994f0221b0c46be4a1f8e10b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -272,6 +272,7 @@ public class ServerPlayer extends Player {
|
||||
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
|
||||
private boolean tpsBar = false; // Purpur
|
||||
private boolean compassBar = false; // Purpur
|
||||
+ private boolean ramBar = false; // Purpur
|
||||
|
||||
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
|
||||
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
|
||||
@@ -510,6 +511,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (nbt.contains("Purpur.RamBar")) { this.ramBar = nbt.getBoolean("Purpur.RamBar"); } // Purpur
|
||||
if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur
|
||||
if (nbt.contains("Purpur.CompassBar")) { this.compassBar = nbt.getBoolean("Purpur.CompassBar"); } // Purpur
|
||||
}
|
||||
@@ -578,6 +580,7 @@ public class ServerPlayer extends Player {
|
||||
}
|
||||
this.getBukkitEntity().setExtraData(nbt); // CraftBukkit
|
||||
|
||||
+ nbt.putBoolean("Purpur.RamBar", this.ramBar); // Purpur
|
||||
nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur
|
||||
nbt.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur
|
||||
}
|
||||
@@ -2573,5 +2576,14 @@ public class ServerPlayer extends Player {
|
||||
public void compassBar(boolean compassBar) {
|
||||
this.compassBar = compassBar;
|
||||
}
|
||||
+
|
||||
+ public boolean ramBar() {
|
||||
+ return this.ramBar;
|
||||
+ }
|
||||
+
|
||||
+ public void ramBar(boolean ramBar) {
|
||||
+ this.ramBar = ramBar;
|
||||
+ }
|
||||
+
|
||||
// Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index e56151fe0dbc0c867dff728a55daa35c7714d3a6..afdee99c7d5ecedf8d2f6856f0aa9271c6bbb23d 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -175,6 +175,17 @@ public class LeafConfig {
|
||||
public static BossBar.Color commandCompassBarProgressColor = BossBar.Color.BLUE;
|
||||
public static float commandCompassBarProgressPercent = 1.0F;
|
||||
public static int commandCompassBarTickInterval = 5;
|
||||
+ public static String ramCommandOutput = "<green>Ram Usage: <used>/<xmx> (<percent>)";
|
||||
+ public static String rambarCommandOutput = "<green>Rambar toggled <onoff> for <target>";
|
||||
+ public static String commandRamBarTitle = "<gray>Ram<yellow>:</yellow> <used>/<xmx> (<percent>)";
|
||||
+ public static BossBar.Overlay commandRamBarProgressOverlay = BossBar.Overlay.NOTCHED_20;
|
||||
+ public static BossBar.Color commandRamBarProgressColorGood = BossBar.Color.GREEN;
|
||||
+ public static BossBar.Color commandRamBarProgressColorMedium = BossBar.Color.YELLOW;
|
||||
+ public static BossBar.Color commandRamBarProgressColorLow = BossBar.Color.RED;
|
||||
+ public static String commandRamBarTextColorGood = "<gradient:#55ff55:#00aa00><text></gradient>";
|
||||
+ public static String commandRamBarTextColorMedium = "<gradient:#ffff55:#ffaa00><text></gradient>";
|
||||
+ public static String commandRamBarTextColorLow = "<gradient:#ff5555:#aa0000><text></gradient>";
|
||||
+ public static int commandRamBarTickInterval = 20;
|
||||
|
||||
private static void commandSettings() {
|
||||
commandTPSBarTitle = getString("settings.command.tpsbar.title", commandTPSBarTitle);
|
||||
@@ -194,6 +205,17 @@ public class LeafConfig {
|
||||
commandCompassBarProgressPercent = (float) getDouble("settings.command.compass.percent", commandCompassBarProgressPercent);
|
||||
commandCompassBarTickInterval = getInt("settings.command.compass.tick-interval", commandCompassBarTickInterval);
|
||||
|
||||
+ ramCommandOutput = getString("settings.messages.ram-command-output", ramCommandOutput);
|
||||
+ rambarCommandOutput = getString("settings.messages.rambar-command-output", rambarCommandOutput);
|
||||
+ commandRamBarTitle = getString("settings.command.rambar.title", commandRamBarTitle);
|
||||
+ commandRamBarProgressOverlay = BossBar.Overlay.valueOf(getString("settings.command.rambar.overlay", commandRamBarProgressOverlay.name()));
|
||||
+ commandRamBarProgressColorGood = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.good", commandRamBarProgressColorGood.name()));
|
||||
+ commandRamBarProgressColorMedium = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.medium", commandRamBarProgressColorMedium.name()));
|
||||
+ commandRamBarProgressColorLow = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.low", commandRamBarProgressColorLow.name()));
|
||||
+ commandRamBarTextColorGood = getString("settings.command.rambar.text-color.good", commandRamBarTextColorGood);
|
||||
+ commandRamBarTextColorMedium = getString("settings.command.rambar.text-color.medium", commandRamBarTextColorMedium);
|
||||
+ commandRamBarTextColorLow = getString("settings.command.rambar.text-color.low", commandRamBarTextColorLow);
|
||||
+ commandRamBarTickInterval = getInt("settings.command.rambar.tick-interval", commandRamBarTickInterval);
|
||||
}
|
||||
|
||||
public static boolean compassItemShowsBossBar = false;
|
||||
diff --git a/src/main/java/org/dreeam/leaf/commands/RamBarCommand.java b/src/main/java/org/dreeam/leaf/commands/RamBarCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..084be8ead4845af5669dbbebc3ebc80facb3e454
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/commands/RamBarCommand.java
|
||||
@@ -0,0 +1,43 @@
|
||||
+package org.dreeam.leaf.commands;
|
||||
+
|
||||
+import com.mojang.brigadier.CommandDispatcher;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.commands.Commands;
|
||||
+import net.minecraft.commands.arguments.EntityArgument;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+import org.dreeam.leaf.tasks.RamBarTask;
|
||||
+
|
||||
+import java.util.Collection;
|
||||
+import java.util.Collections;
|
||||
+
|
||||
+public class RamBarCommand {
|
||||
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+ dispatcher.register(Commands.literal("rambar")
|
||||
+ .requires(listener -> listener.hasPermission(2))
|
||||
+ .executes(context -> execute(context.getSource(), Collections.singleton(context.getSource().getPlayerOrException())))
|
||||
+ .then(Commands.argument("targets", EntityArgument.players())
|
||||
+ .executes((context) -> execute(context.getSource(), EntityArgument.getPlayers(context, "targets")))
|
||||
+ )
|
||||
+ ).setPermission("bukkit.command.rambar");
|
||||
+ }
|
||||
+
|
||||
+ private static int execute(CommandSourceStack sender, Collection<ServerPlayer> targets) {
|
||||
+ for (ServerPlayer player : targets) {
|
||||
+ boolean result = RamBarTask.instance().togglePlayer(player.getBukkitEntity());
|
||||
+ player.ramBar(result);
|
||||
+
|
||||
+ Component output = MiniMessage.miniMessage().deserialize(LeafConfig.rambarCommandOutput,
|
||||
+ Placeholder.component("onoff", Component.translatable(result ? "options.on" : "options.off")
|
||||
+ .color(result ? NamedTextColor.GREEN : NamedTextColor.RED)),
|
||||
+ Placeholder.parsed("target", player.getGameProfile().getName()));
|
||||
+
|
||||
+ sender.sendSuccess(output, false);
|
||||
+ }
|
||||
+ return targets.size();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/commands/RamCommand.java b/src/main/java/org/dreeam/leaf/commands/RamCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6cfb2791afed4122782ae5a8a5a9ecef698d8823
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/commands/RamCommand.java
|
||||
@@ -0,0 +1,30 @@
|
||||
+package org.dreeam.leaf.commands;
|
||||
+
|
||||
+import com.mojang.brigadier.CommandDispatcher;
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
+import net.minecraft.commands.CommandSourceStack;
|
||||
+import net.minecraft.commands.Commands;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+import org.dreeam.leaf.tasks.RamBarTask;
|
||||
+
|
||||
+public class RamCommand {
|
||||
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+ dispatcher.register(Commands.literal("ram")
|
||||
+ .requires(listener -> listener.hasPermission(2))
|
||||
+ .executes(context -> {
|
||||
+ CommandSourceStack sender = context.getSource();
|
||||
+ RamBarTask ramBar = RamBarTask.instance();
|
||||
+ sender.sendSuccess(PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(LeafConfig.ramCommandOutput,
|
||||
+ Placeholder.component("allocated", ramBar.format(ramBar.getAllocated())),
|
||||
+ Placeholder.component("used", ramBar.format(ramBar.getUsed())),
|
||||
+ Placeholder.component("xmx", ramBar.format(ramBar.getXmx())),
|
||||
+ Placeholder.component("xms", ramBar.format(ramBar.getXms())),
|
||||
+ Placeholder.unparsed("percent", ((int) (ramBar.getPercent() * 100)) + "%")
|
||||
+ )), false);
|
||||
+ return 1;
|
||||
+ })
|
||||
+ ).setPermission("bukkit.command.ram");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
index 7dacf4f21d082dd9a19db6e5122d06b5bda8fc95..46644c72bf1db3cb86ffbf50dd7d723cb04e04e3 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/BossBarTask.java
|
||||
@@ -91,11 +91,13 @@ public abstract class BossBarTask extends BukkitRunnable {
|
||||
public static void startAll() {
|
||||
TPSBarTask.instance().start();
|
||||
CompassTask.instance().start();
|
||||
+ RamBarTask.instance().start();
|
||||
}
|
||||
|
||||
public static void stopAll() {
|
||||
TPSBarTask.instance().stop();
|
||||
CompassTask.instance().stop();
|
||||
+ RamBarTask.instance().stop();
|
||||
}
|
||||
|
||||
public static void addToAll(ServerPlayer player) {
|
||||
@@ -106,10 +108,14 @@ public abstract class BossBarTask extends BukkitRunnable {
|
||||
if (player.compassBar()) {
|
||||
CompassTask.instance().addPlayer(bukkit);
|
||||
}
|
||||
+ if (player.ramBar()) {
|
||||
+ RamBarTask.instance().addPlayer(bukkit);
|
||||
+ }
|
||||
}
|
||||
|
||||
public static void removeFromAll(Player player) {
|
||||
TPSBarTask.instance().removePlayer(player);
|
||||
CompassTask.instance().removePlayer(player);
|
||||
+ RamBarTask.instance().removePlayer(player);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/tasks/RamBarTask.java b/src/main/java/org/dreeam/leaf/tasks/RamBarTask.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c0d2f4f9fdd60f89376a18c88cf82012acd62da0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/tasks/RamBarTask.java
|
||||
@@ -0,0 +1,117 @@
|
||||
+package org.dreeam.leaf.tasks;
|
||||
+
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.dreeam.leaf.LeafConfig;
|
||||
+
|
||||
+import java.lang.management.ManagementFactory;
|
||||
+import java.lang.management.MemoryUsage;
|
||||
+
|
||||
+public class RamBarTask extends BossBarTask {
|
||||
+ private static RamBarTask instance;
|
||||
+ private long allocated = 0L;
|
||||
+ private long used = 0L;
|
||||
+ private long xmx = 0L;
|
||||
+ private long xms = 0L;
|
||||
+ private float percent = 0F;
|
||||
+ private int tick = 0;
|
||||
+
|
||||
+ public static RamBarTask instance() {
|
||||
+ if (instance == null) {
|
||||
+ instance = new RamBarTask();
|
||||
+ }
|
||||
+ return instance;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ BossBar createBossBar() {
|
||||
+ return BossBar.bossBar(Component.text(""), 0.0F, instance().getBossBarColor(), LeafConfig.commandRamBarProgressOverlay);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ void updateBossBar(BossBar bossbar, Player player) {
|
||||
+ bossbar.progress(getBossBarProgress());
|
||||
+ bossbar.color(getBossBarColor());
|
||||
+ bossbar.name(MiniMessage.miniMessage().deserialize(LeafConfig.commandRamBarTitle,
|
||||
+ Placeholder.component("allocated", format(this.allocated)),
|
||||
+ Placeholder.component("used", format(this.used)),
|
||||
+ Placeholder.component("xmx", format(this.xmx)),
|
||||
+ Placeholder.component("xms", format(this.xms)),
|
||||
+ Placeholder.unparsed("percent", ((int) (this.percent * 100)) + "%")
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ if (++this.tick < LeafConfig.commandRamBarTickInterval) {
|
||||
+ return;
|
||||
+ }
|
||||
+ this.tick = 0;
|
||||
+
|
||||
+ MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
||||
+
|
||||
+ this.allocated = heap.getCommitted();
|
||||
+ this.used = heap.getUsed();
|
||||
+ this.xmx = heap.getMax();
|
||||
+ this.xms = heap.getInit();
|
||||
+ this.percent = Math.max(Math.min((float) this.used / this.xmx, 1.0F), 0.0F);
|
||||
+
|
||||
+ super.run();
|
||||
+ }
|
||||
+
|
||||
+ private float getBossBarProgress() {
|
||||
+ return this.percent;
|
||||
+ }
|
||||
+
|
||||
+ private BossBar.Color getBossBarColor() {
|
||||
+ if (this.percent < 0.5F) {
|
||||
+ return LeafConfig.commandRamBarProgressColorGood;
|
||||
+ } else if (this.percent < 0.75F) {
|
||||
+ return LeafConfig.commandRamBarProgressColorMedium;
|
||||
+ } else {
|
||||
+ return LeafConfig.commandRamBarProgressColorLow;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public Component format(long v) {
|
||||
+ String color;
|
||||
+ if (this.percent < 0.60F) {
|
||||
+ color = LeafConfig.commandRamBarTextColorGood;
|
||||
+ } else if (this.percent < 0.85F) {
|
||||
+ color = LeafConfig.commandRamBarTextColorMedium;
|
||||
+ } else {
|
||||
+ color = LeafConfig.commandRamBarTextColorLow;
|
||||
+ }
|
||||
+ String value;
|
||||
+ if (v < 1024) {
|
||||
+ value = v + "B";
|
||||
+ } else {
|
||||
+ int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
|
||||
+ value = String.format("%.1f%s", (double) v / (1L << (z * 10)), "BKMGTPE".charAt(z));
|
||||
+ }
|
||||
+ return MiniMessage.miniMessage().deserialize(color, Placeholder.unparsed("text", value));
|
||||
+ }
|
||||
+
|
||||
+ public long getAllocated() {
|
||||
+ return this.allocated;
|
||||
+ }
|
||||
+
|
||||
+ public long getUsed() {
|
||||
+ return this.used;
|
||||
+ }
|
||||
+
|
||||
+ public long getXmx() {
|
||||
+ return this.xmx;
|
||||
+ }
|
||||
+
|
||||
+ public long getXms() {
|
||||
+ return this.xms;
|
||||
+ }
|
||||
+
|
||||
+ public float getPercent() {
|
||||
+ return this.percent;
|
||||
+ }
|
||||
+}
|
||||
58
patches/server/0011-Purpur-Lagging-threshold.patch
Normal file
58
patches/server/0011-Purpur-Lagging-threshold.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Tue, 23 Jul 2019 10:07:16 -0500
|
||||
Subject: [PATCH] Purpur: Lagging threshold
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index ab0a4a36241bee59b142df65736003c69dcb3dd4..411fae7132b1d1763712594a18cff10d612cef7e 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Spigot end
|
||||
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
|
||||
public static long currentTickLong = 0L; // Paper
|
||||
+ public boolean lagging = false; // Purpur
|
||||
|
||||
public volatile Thread shutdownThread; // Paper
|
||||
public volatile boolean abnormalExit = false; // Paper
|
||||
@@ -1159,6 +1160,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.recentTps[1] = tps5.getAverage();
|
||||
this.recentTps[2] = tps15.getAverage();
|
||||
// Paper end
|
||||
+ lagging = recentTps[0] < org.dreeam.leaf.LeafConfig.laggingThreshold; // Purpur
|
||||
tickSection = curTime;
|
||||
}
|
||||
// Spigot end
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 07b40f503358987339937bb8db5a3ee54c1b08c8..faff1f560eef2429621b4b0a4d760f9a558dcb73 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2943,4 +2943,11 @@ public final class CraftServer implements Server {
|
||||
}
|
||||
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start
|
||||
+ @Override
|
||||
+ public boolean isLagging() {
|
||||
+ return getServer().lagging;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index afdee99c7d5ecedf8d2f6856f0aa9271c6bbb23d..a723d5a6bb69543072b8e9a7082ba3f0e89d453e 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -222,4 +222,9 @@ public class LeafConfig {
|
||||
private static void itemSettings() {
|
||||
compassItemShowsBossBar = getBoolean("gameplay-mechanics.item.compass.holding-shows-bossbar", compassItemShowsBossBar);
|
||||
}
|
||||
+
|
||||
+ public static double laggingThreshold = 19.0D;
|
||||
+ private static void tickLoopSettings() {
|
||||
+ laggingThreshold = getDouble("settings.lagging-threshold", laggingThreshold);
|
||||
+ }
|
||||
}
|
||||
40
patches/server/0012-Purpur-Configurable-TPS-Catchup.patch
Normal file
40
patches/server/0012-Purpur-Configurable-TPS-Catchup.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 26 Mar 2020 19:06:22 -0500
|
||||
Subject: [PATCH] Purpur: Configurable TPS Catchup
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 411fae7132b1d1763712594a18cff10d612cef7e..75daffc4eaa831708f1ccfa5370ddf1871998033 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1179,6 +1179,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.profiler.popPush("nextTickWait");
|
||||
this.mayHaveDelayedTasks = true;
|
||||
this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
|
||||
+ // Purpur start - tps catchup
|
||||
+ if (org.dreeam.leaf.LeafConfig.tpsCatchup) {
|
||||
+ this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
|
||||
+ } else {
|
||||
+ this.delayedTasksMaxNextTickTime = this.nextTickTime = curTime / 1000000L + 50L;
|
||||
+ }
|
||||
+ // Purpur end - tps catchup
|
||||
this.waitUntilNextTick();
|
||||
this.profiler.pop();
|
||||
this.endMetricsRecordingTick();
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index a723d5a6bb69543072b8e9a7082ba3f0e89d453e..66092bc87472278898743971dd80244cb750297e 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -227,4 +227,9 @@ public class LeafConfig {
|
||||
private static void tickLoopSettings() {
|
||||
laggingThreshold = getDouble("settings.lagging-threshold", laggingThreshold);
|
||||
}
|
||||
+
|
||||
+ public static boolean tpsCatchup = true;
|
||||
+ private static void tpsCatchup() {
|
||||
+ tpsCatchup = getBoolean("settings.tps-catchup", tpsCatchup);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sun, 5 Jul 2020 23:40:16 -0500
|
||||
Subject: [PATCH] Purpur: Add allow water in end world option
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
index 5c6aa9c464784ad5ee366412d080c72d3d22a76f..35d819aa2e660263cf6a5a0c09a6e73f7a89389b 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
@@ -166,7 +166,7 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
// CraftBukkit end
|
||||
if (!flag1) {
|
||||
return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit
|
||||
- } else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) {
|
||||
+ } else if ((world.dimensionType().ultraWarm() || (world.isTheEnd() && !org.dreeam.leaf.LeafConfig.allowWaterPlacementInTheEnd)) && this.content.is(FluidTags.WATER)) { // Purpur
|
||||
int i = blockposition.getX();
|
||||
int j = blockposition.getY();
|
||||
int k = blockposition.getZ();
|
||||
@@ -174,7 +174,7 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
world.playSound(entityhuman, blockposition, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
|
||||
|
||||
for (int l = 0; l < 8; ++l) {
|
||||
- world.addParticle(ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 0.0D, 0.0D, 0.0D);
|
||||
+ ((ServerLevel) world).sendParticles(null, ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 1, 0.0D, 0.0D, 0.0D, 0.0D, true); // Purpur
|
||||
}
|
||||
|
||||
return true;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index edd2c236ca7c37e1a3aec0048b8974f4cd62f2cc..62aff29485f124880739e7d2b5fb0d8a9d957741 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -1635,4 +1635,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return null;
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start
|
||||
+ public boolean isNether() {
|
||||
+ return getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isTheEnd() {
|
||||
+ return getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
index 64206d94a5bf210116d208f9678618b905a61428..fbb06c5db6f80008a54563b7d959e55e5ba96673 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java
|
||||
@@ -31,7 +31,7 @@ public class IceBlock extends HalfTransparentBlock {
|
||||
public void afterDestroy(Level world, BlockPos pos, ItemStack stack) {
|
||||
// Paper end
|
||||
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) {
|
||||
- if (world.dimensionType().ultraWarm()) {
|
||||
+ if (world.isNether() || (world.isTheEnd() && !org.dreeam.leaf.LeafConfig.allowWaterPlacementInTheEnd)) { // Purpur
|
||||
world.removeBlock(pos, false);
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class IceBlock extends HalfTransparentBlock {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- if (world.dimensionType().ultraWarm()) {
|
||||
+ if (world.isNether() || (world.isTheEnd() && !org.dreeam.leaf.LeafConfig.allowWaterPlacementInTheEnd)) { // Purpur
|
||||
world.removeBlock(pos, false);
|
||||
} else {
|
||||
world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState());
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 66092bc87472278898743971dd80244cb750297e..06664bb40fe4b55998e7a0957cbb4b9fa4f8b05f 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -232,4 +232,9 @@ public class LeafConfig {
|
||||
private static void tpsCatchup() {
|
||||
tpsCatchup = getBoolean("settings.tps-catchup", tpsCatchup);
|
||||
}
|
||||
+
|
||||
+ public static boolean allowWaterPlacementInTheEnd = true;
|
||||
+ private static void allowWaterPlacementInEnd() {
|
||||
+ allowWaterPlacementInTheEnd = getBoolean("settings.allow-water-placement-in-the-end", allowWaterPlacementInTheEnd);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Encode42 <me@encode42.dev>
|
||||
Date: Wed, 24 Mar 2021 20:30:37 -0400
|
||||
Subject: [PATCH] Purpur: Configurable sponge absorption
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
Allows the total area and radius of water blocks the sponge can absorb to be changed.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
index 7304b2659eb45bc4bc9fa7c43e6ca07221d0fc73..35a69bb50bc0575dd4f285cc9499d085fe6512ea 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
|
||||
@@ -76,13 +76,13 @@ public class SpongeBlock extends Block {
|
||||
if (fluid.is(FluidTags.WATER)) {
|
||||
if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock(blockList, blockposition2, iblockdata).isEmpty()) { // CraftBukkit
|
||||
++i;
|
||||
- if (j < 6) {
|
||||
+ if (j < org.dreeam.leaf.LeafConfig.spongeAbsorptionRadius) { // Purpur
|
||||
queue.add(new Tuple<>(blockposition2, j + 1));
|
||||
}
|
||||
} else if (iblockdata.getBlock() instanceof LiquidBlock) {
|
||||
blockList.setBlock(blockposition2, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit
|
||||
++i;
|
||||
- if (j < 6) {
|
||||
+ if (j < org.dreeam.leaf.LeafConfig.spongeAbsorptionRadius) { // Purpur
|
||||
queue.add(new Tuple<>(blockposition2, j + 1));
|
||||
}
|
||||
} else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) {
|
||||
@@ -93,14 +93,14 @@ public class SpongeBlock extends Block {
|
||||
blockList.setBlock(blockposition2, Blocks.AIR.defaultBlockState(), 3);
|
||||
// CraftBukkit end
|
||||
++i;
|
||||
- if (j < 6) {
|
||||
+ if (j < org.dreeam.leaf.LeafConfig.spongeAbsorptionRadius) { // Purpur
|
||||
queue.add(new Tuple<>(blockposition2, j + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- if (i > 64) {
|
||||
+ if (i > org.dreeam.leaf.LeafConfig.spongeAbsorptionArea) { // Purpur
|
||||
break;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 06664bb40fe4b55998e7a0957cbb4b9fa4f8b05f..680ada855140ad86c5c953c7357fc745b308b334 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -237,4 +237,11 @@ public class LeafConfig {
|
||||
private static void allowWaterPlacementInEnd() {
|
||||
allowWaterPlacementInTheEnd = getBoolean("settings.allow-water-placement-in-the-end", allowWaterPlacementInTheEnd);
|
||||
}
|
||||
+
|
||||
+ public static int spongeAbsorptionArea = 64;
|
||||
+ public static int spongeAbsorptionRadius = 6;
|
||||
+ private static void spongeSettings() {
|
||||
+ spongeAbsorptionArea = getInt("blocks.sponge.absorption.area", spongeAbsorptionArea);
|
||||
+ spongeAbsorptionRadius = getInt("blocks.sponge.absorption.radius", spongeAbsorptionRadius);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: DoctaEnkoda <bierquejason@gmail.com>
|
||||
Date: Sun, 2 May 2021 23:14:54 +0200
|
||||
Subject: [PATCH] Purpur: Configurable piston push limit
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java b/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java
|
||||
index 744d91546d1a810f60a43c15ed74b4158f341a4a..460609a50d0f68c191f0fd529a7dc582ac0a2317 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonStructureResolver.java
|
||||
@@ -86,7 +86,7 @@ public class PistonStructureResolver {
|
||||
return true;
|
||||
} else {
|
||||
int i = 1;
|
||||
- if (i + this.toPush.size() > 12) {
|
||||
+ if (i + this.toPush.size() > org.dreeam.leaf.LeafConfig.pistonBlockPushLimit) { // Purpur
|
||||
return false;
|
||||
} else {
|
||||
while(isSticky(blockState)) {
|
||||
@@ -98,7 +98,7 @@ public class PistonStructureResolver {
|
||||
}
|
||||
|
||||
++i;
|
||||
- if (i + this.toPush.size() > 12) {
|
||||
+ if (i + this.toPush.size() > org.dreeam.leaf.LeafConfig.pistonBlockPushLimit) { // Purpur
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public class PistonStructureResolver {
|
||||
return true;
|
||||
}
|
||||
|
||||
- if (this.toPush.size() >= 12) {
|
||||
+ if (this.toPush.size() >= org.dreeam.leaf.LeafConfig.pistonBlockPushLimit) { // Purpur
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 680ada855140ad86c5c953c7357fc745b308b334..e04d0dc3ed108edee9b8cabea56f86556ac9fb78 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -244,4 +244,9 @@ public class LeafConfig {
|
||||
spongeAbsorptionArea = getInt("blocks.sponge.absorption.area", spongeAbsorptionArea);
|
||||
spongeAbsorptionRadius = getInt("blocks.sponge.absorption.radius", spongeAbsorptionRadius);
|
||||
}
|
||||
+
|
||||
+ public static int pistonBlockPushLimit = 12;
|
||||
+ private static void pistonSettings() {
|
||||
+ pistonBlockPushLimit = getInt("blocks.piston.block-push-limit", pistonBlockPushLimit);
|
||||
+ }
|
||||
}
|
||||
145
patches/server/0016-Purpur-Configurable-broadcast-settings.patch
Normal file
145
patches/server/0016-Purpur-Configurable-broadcast-settings.patch
Normal file
@@ -0,0 +1,145 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: DoctaEnkoda <bierquejason@gmail.com>
|
||||
Date: Mon, 3 May 2021 01:33:14 +0200
|
||||
Subject: [PATCH] Purpur: Configurable broadcast settings
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
index a0c19503aabab5378d672a30163d35a5ba05b6c1..0b089a2032d468532a40e81cb0e9eda4cf184ad0 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -297,6 +297,7 @@ public class PlayerAdvancements {
|
||||
advancement.getRewards().grant(this.player);
|
||||
// Paper start - Add Adventure message to PlayerAdvancementDoneEvent
|
||||
if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
|
||||
+ if (org.dreeam.leaf.LeafConfig.advancementOnlyBroadcastToAffectedPlayer) this.player.sendMessage(message); else // Purpur
|
||||
this.playerList.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), false);
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 95db6657cd65b71f994f0221b0c46be4a1f8e10b..0ff21883cff37d1df7fda9b2cb93abcfd43f6482 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -949,6 +949,7 @@ public class ServerPlayer extends Player {
|
||||
}));
|
||||
Team scoreboardteambase = this.getTeam();
|
||||
|
||||
+ if (org.dreeam.leaf.LeafConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendSystemMessage(ichatbasecomponent); else // Purpur
|
||||
if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != Team.Visibility.ALWAYS) {
|
||||
if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
|
||||
this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent);
|
||||
@@ -1749,6 +1750,26 @@ public class ServerPlayer extends Player {
|
||||
this.lastSentExp = -1; // CraftBukkit - Added to reset
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public void sendActionBarMessage(@Nullable String message) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ sendActionBarMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendActionBarMessage(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ if (message != null) {
|
||||
+ sendActionBarMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendActionBarMessage(@Nullable Component message) {
|
||||
+ if (message != null) {
|
||||
+ displayClientMessage(message, true);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
public void displayClientMessage(Component message, boolean overlay) {
|
||||
this.sendSystemMessage(message, overlay);
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 1895a3919d43e8e4f8399c75db8482df9e78bb3d..7b731d38c06a525d9a88f88ee75f32d159afdedc 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1088,6 +1088,20 @@ public abstract class PlayerList {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
+ // Purpur Start
|
||||
+ public void broadcastMiniMessage(@Nullable String message, boolean overlay) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ this.broadcastMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message), overlay);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void broadcastMessage(@Nullable net.kyori.adventure.text.Component message, boolean overlay) {
|
||||
+ if (message != null) {
|
||||
+ this.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), overlay);
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
|
||||
Iterator iterator = this.players.iterator();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
index 8795c94e6b6474addddbb0b337a962e8fac46b2b..f2ef4d93e070167d70f597e8893bf29b53433a28 100644
|
||||
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
||||
@@ -256,6 +256,15 @@ public class DamageSource {
|
||||
return entityliving1 != null ? Component.translatable(s1, entity.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, entity.getDisplayName());
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ public Component getLocalizedDeathMessage(String str, LivingEntity entity) {
|
||||
+ net.kyori.adventure.text.Component name = io.papermc.paper.adventure.PaperAdventure.asAdventure(entity.getDisplayName());
|
||||
+ net.kyori.adventure.text.minimessage.tag.resolver.TagResolver template = net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("player", name);
|
||||
+ net.kyori.adventure.text.Component component = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(str, template);
|
||||
+ return io.papermc.paper.adventure.PaperAdventure.asVanilla(component);
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
public boolean isFire() {
|
||||
return this.isFireSource;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 374b46c344ca868cab7c47be69cb005eb90319e8..37f1e4aa89da81fcae2d38bb741f3386950bdf51 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3853,6 +3853,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
return SlotAccess.NULL;
|
||||
}
|
||||
|
||||
+ // Purpur Start
|
||||
+ public void sendMiniMessage(@Nullable String message) {
|
||||
+ if (message != null && !message.isEmpty()) {
|
||||
+ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void sendMessage(@Nullable net.kyori.adventure.text.Component message) {
|
||||
+ if (message != null) {
|
||||
+ this.sendSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message));
|
||||
+ }
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
@Override
|
||||
public void sendSystemMessage(Component message) {}
|
||||
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index e04d0dc3ed108edee9b8cabea56f86556ac9fb78..040c1f584c525990ec844cba9f01df5b33fa2a37 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -249,4 +249,11 @@ public class LeafConfig {
|
||||
private static void pistonSettings() {
|
||||
pistonBlockPushLimit = getInt("blocks.piston.block-push-limit", pistonBlockPushLimit);
|
||||
}
|
||||
+
|
||||
+ public static boolean advancementOnlyBroadcastToAffectedPlayer = false;
|
||||
+ public static boolean deathMessageOnlyBroadcastToAffectedPlayer = false;
|
||||
+ private static void broadcastSettings() {
|
||||
+ advancementOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.advancement.only-broadcast-to-affected-player", advancementOnlyBroadcastToAffectedPlayer);
|
||||
+ deathMessageOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.death.only-broadcast-to-affected-player", deathMessageOnlyBroadcastToAffectedPlayer);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: DoctaEnkoda <bierquejason@gmail.com>
|
||||
Date: Thu, 24 Jun 2021 02:28:32 +0200
|
||||
Subject: [PATCH] Purpur: Allow player join full server by permission
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 7b731d38c06a525d9a88f88ee75f32d159afdedc..37a46d95793b43f5cb6ade9e2f2d20bf0942f21e 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -792,7 +792,7 @@ public abstract class PlayerList {
|
||||
event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure
|
||||
} else {
|
||||
// return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null;
|
||||
- if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) {
|
||||
+ if (this.players.size() >= this.maxPlayers && !(player.hasPermission("purpur.joinfullserver") || this.canBypassPlayerLimit(gameprofile))) { // Purpur
|
||||
event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: DoctaEnkoda <bierquejason@gmail.com>
|
||||
Date: Mon, 13 Sep 2021 04:48:21 +0200
|
||||
Subject: [PATCH] Purpur: Halloween options and optimizations
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
||||
index 1572a81ce1718964d795f2a2a411402f88901c73..ae2c84af8baaf1bba9b0debe3774321417d77413 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
|
||||
@@ -246,7 +246,7 @@ public class Bat extends AmbientCreature {
|
||||
int i = world.getMaxLocalRawBrightness(pos);
|
||||
byte b0 = 4;
|
||||
|
||||
- if (Bat.isHalloween()) {
|
||||
+ if (Bat.isHalloweenSeason(world.getMinecraftWorld())) { // Purpur
|
||||
b0 = 7;
|
||||
} else if (random.nextBoolean()) {
|
||||
return false;
|
||||
@@ -260,6 +260,7 @@ public class Bat extends AmbientCreature {
|
||||
private static boolean isSpookySeason = false;
|
||||
private static final int ONE_HOUR = 20 * 60 * 60;
|
||||
private static int lastSpookyCheck = -ONE_HOUR;
|
||||
+ public static boolean isHalloweenSeason(Level level) { return org.dreeam.leaf.LeafConfig.forceHalloweenSeason || isHalloween(); } // Purpur
|
||||
private static boolean isHalloween() {
|
||||
if (net.minecraft.server.MinecraftServer.currentTick - lastSpookyCheck > ONE_HOUR) {
|
||||
LocalDate localdate = LocalDate.now();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
index b8abee145fc92faddef98da913eca7715b6bfc03..41de63fdcfe48c2a77f2d04e5bffbca41c98afe3 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
|
||||
@@ -158,11 +158,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
|
||||
this.reassessWeaponGoal();
|
||||
this.setCanPickUpLoot(this.level.paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper
|
||||
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
|
||||
- LocalDate localdate = LocalDate.now();
|
||||
- int i = localdate.get(ChronoField.DAY_OF_MONTH);
|
||||
- int j = localdate.get(ChronoField.MONTH_OF_YEAR);
|
||||
-
|
||||
- if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) {
|
||||
+ if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(world.getMinecraftWorld()) && this.random.nextFloat() < org.dreeam.leaf.LeafConfig.chanceHeadHalloweenOnEntity) { // Purpur
|
||||
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
|
||||
this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 9976205537cfe228735687f1e9c52c74ac025690..dfe4c6d2bf9bee2e019635d02f01dc08f99c160e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -559,11 +559,7 @@ public class Zombie extends Monster {
|
||||
}
|
||||
|
||||
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
|
||||
- LocalDate localdate = LocalDate.now();
|
||||
- int i = localdate.get(ChronoField.DAY_OF_MONTH);
|
||||
- int j = localdate.get(ChronoField.MONTH_OF_YEAR);
|
||||
-
|
||||
- if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) {
|
||||
+ if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(world.getMinecraftWorld()) && this.random.nextFloat() < org.dreeam.leaf.LeafConfig.chanceHeadHalloweenOnEntity) { // Purpur
|
||||
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
|
||||
this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F;
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 040c1f584c525990ec844cba9f01df5b33fa2a37..2855f8c4684cb9afee1bd8a4c2ae82d45ef1ea2b 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -256,4 +256,11 @@ public class LeafConfig {
|
||||
advancementOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.advancement.only-broadcast-to-affected-player", advancementOnlyBroadcastToAffectedPlayer);
|
||||
deathMessageOnlyBroadcastToAffectedPlayer = getBoolean("settings.broadcasts.death.only-broadcast-to-affected-player", deathMessageOnlyBroadcastToAffectedPlayer);
|
||||
}
|
||||
+
|
||||
+ public static boolean forceHalloweenSeason = false;
|
||||
+ public static float chanceHeadHalloweenOnEntity = 0.25F;
|
||||
+ private static void halloweenSetting() {
|
||||
+ forceHalloweenSeason = getBoolean("gameplay-mechanics.halloween.force", forceHalloweenSeason);
|
||||
+ chanceHeadHalloweenOnEntity = (float) getDouble("gameplay-mechanics.halloween.head-chance", chanceHeadHalloweenOnEntity);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Wed, 30 Sep 2020 14:32:46 -0700
|
||||
Subject: [PATCH] Purpur: Persistent BlockEntity Lore and DisplayName
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
Makes it so that when a BlockEntity is placed in the world and then broken,
|
||||
the dropped ItemStack retains any original custom display name/lore.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
index b0204af850ee182773ad458208cccd946ad148d5..f74e420b1791df528a30a1213bb0076b4d9d545d 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
|
||||
@@ -153,7 +153,24 @@ public class BlockItem extends Item {
|
||||
}
|
||||
|
||||
protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, @Nullable Player player, ItemStack stack, BlockState state) {
|
||||
- return BlockItem.updateCustomBlockEntityTag(world, player, pos, stack);
|
||||
+ // Purpur start
|
||||
+ boolean handled = updateCustomBlockEntityTag(world, player, pos, stack);
|
||||
+ if (org.dreeam.leaf.LeafConfig.persistentTileEntityDisplayNames && stack.hasTag()) {
|
||||
+ CompoundTag display = stack.getTagElement("display");
|
||||
+ if (display != null) {
|
||||
+ BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
+ if (blockEntity != null) {
|
||||
+ if (display.contains("Name", 8)) {
|
||||
+ blockEntity.setPersistentDisplayName(display.getString("Name"));
|
||||
+ }
|
||||
+ if (display.contains("Lore", 9)) {
|
||||
+ blockEntity.setPersistentLore(display.getList("Lore", 8));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return handled;
|
||||
+ // Purpur end
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index 7b71073027f4cf79736546500ededdfbb83d968e..98c9c1899a311e76179f72fa1c43830fb5b9c521 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -63,6 +63,13 @@ import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// Purpur start
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.ListTag;
|
||||
+import net.minecraft.nbt.StringTag;
|
||||
+import net.minecraft.world.Nameable;
|
||||
+// Purpur end
|
||||
+
|
||||
public class Block extends BlockBehaviour implements ItemLike {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -325,7 +332,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) {
|
||||
if (world instanceof ServerLevel) {
|
||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> {
|
||||
- Block.popResource((ServerLevel) world, pos, itemstack);
|
||||
+ Block.popResource((ServerLevel) world, pos, applyDisplayNameAndLoreFromTile(itemstack, blockEntity)); // Purpur
|
||||
});
|
||||
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
|
||||
}
|
||||
@@ -341,7 +348,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.block.CraftBlock.at(world, source), items);
|
||||
event.callEvent();
|
||||
for (var drop : event.getDrops()) {
|
||||
- popResource(world.getMinecraftWorld(), pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
||||
+ popResource(world.getMinecraftWorld(), pos, applyDisplayNameAndLoreFromTile(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop), blockEntity)); // Purpur
|
||||
}
|
||||
state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, true);
|
||||
}
|
||||
@@ -352,13 +359,53 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack stack) {
|
||||
if (world instanceof ServerLevel) {
|
||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, stack).forEach((itemstack1) -> {
|
||||
- Block.popResource(world, pos, itemstack1);
|
||||
+ Block.popResource(world, pos, applyDisplayNameAndLoreFromTile(itemstack1, blockEntity)); // Purpur
|
||||
});
|
||||
state.spawnAfterBreak((ServerLevel) world, pos, stack, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ private static ItemStack applyDisplayNameAndLoreFromTile(ItemStack stack, BlockEntity blockEntity) {
|
||||
+ if (stack.getItem() instanceof BlockItem) {
|
||||
+ if (blockEntity != null && blockEntity.getLevel() instanceof ServerLevel && org.dreeam.leaf.LeafConfig.persistentTileEntityDisplayNames) {
|
||||
+ String name = blockEntity.getPersistentDisplayName();
|
||||
+ ListTag lore = blockEntity.getPersistentLore();
|
||||
+ if (blockEntity instanceof Nameable) {
|
||||
+ Nameable namedTile = (Nameable) blockEntity;
|
||||
+ if (namedTile.hasCustomName()) {
|
||||
+ name = Component.Serializer.toJson(namedTile.getCustomName());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (name != null || lore != null) {
|
||||
+ CompoundTag display = stack.getTagElement("display");
|
||||
+ if (display == null) {
|
||||
+ display = new CompoundTag();
|
||||
+ }
|
||||
+
|
||||
+ if (name != null) {
|
||||
+ display.put("Name", StringTag.valueOf(name));
|
||||
+ }
|
||||
+ if (lore != null) {
|
||||
+ display.put("Lore", lore);
|
||||
+ }
|
||||
+
|
||||
+ CompoundTag tag = stack.getTag();
|
||||
+ if (tag == null) {
|
||||
+ tag = new CompoundTag();
|
||||
+ }
|
||||
+ tag.put("display", display);
|
||||
+
|
||||
+ stack.setTag(tag);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return stack;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
public static void popResource(Level world, BlockPos pos, ItemStack stack) {
|
||||
float f = EntityType.ITEM.getHeight() / 2.0F;
|
||||
// Paper start - don't convert potentially massive numbers to floats
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 58986bc0677c5ea1ad54d7d6d4efa5c2ea233aea..59d616137088af46d4494171fe96ba0129082496 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -6,6 +6,8 @@ import net.minecraft.CrashReportCategory;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.ListTag;
|
||||
+import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -74,10 +76,27 @@ public abstract class BlockEntity {
|
||||
if (persistentDataTag instanceof CompoundTag) {
|
||||
this.persistentDataContainer.putAll((CompoundTag) persistentDataTag);
|
||||
}
|
||||
+ // Purpur start
|
||||
+ if (nbt.contains("Purpur.persistentDisplayName")) {
|
||||
+ this.persistentDisplayName = nbt.getString("Purpur.persistentDisplayName");
|
||||
+ }
|
||||
+ if (nbt.contains("Purpur.persistentLore")) {
|
||||
+ this.persistentLore = nbt.getList("Purpur.persistentLore", 8);
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
- protected void saveAdditional(CompoundTag nbt) {}
|
||||
+ protected void saveAdditional(CompoundTag nbt) {
|
||||
+ // Purpur start
|
||||
+ if (this.persistentDisplayName != null) {
|
||||
+ nbt.put("Purpur.persistentDisplayName", StringTag.valueOf(this.persistentDisplayName));
|
||||
+ }
|
||||
+ if (this.persistentLore != null) {
|
||||
+ nbt.put("Purpur.persistentLore", this.persistentLore);
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+ }
|
||||
|
||||
public final CompoundTag saveWithFullMetadata() {
|
||||
CompoundTag nbttagcompound = this.saveWithoutMetadata();
|
||||
@@ -264,4 +283,24 @@ public abstract class BlockEntity {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Purpur start
|
||||
+ private String persistentDisplayName = null;
|
||||
+ private ListTag persistentLore = null;
|
||||
+
|
||||
+ public void setPersistentDisplayName(String json) {
|
||||
+ this.persistentDisplayName = json;
|
||||
+ }
|
||||
+
|
||||
+ public void setPersistentLore(ListTag lore) {
|
||||
+ this.persistentLore = lore;
|
||||
+ }
|
||||
+
|
||||
+ public String getPersistentDisplayName() {
|
||||
+ return this.persistentDisplayName;
|
||||
+ }
|
||||
+
|
||||
+ public ListTag getPersistentLore() {
|
||||
+ return this.persistentLore;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 2855f8c4684cb9afee1bd8a4c2ae82d45ef1ea2b..f87f4f19738dfe8b58d3dbf0c27933fd3ec93883 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -263,4 +263,9 @@ public class LeafConfig {
|
||||
forceHalloweenSeason = getBoolean("gameplay-mechanics.halloween.force", forceHalloweenSeason);
|
||||
chanceHeadHalloweenOnEntity = (float) getDouble("gameplay-mechanics.halloween.head-chance", chanceHeadHalloweenOnEntity);
|
||||
}
|
||||
+
|
||||
+ public static boolean persistentTileEntityDisplayNames = false;
|
||||
+ private static void tileentitySetting() {
|
||||
+ persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Wed, 27 Jul 2022 00:42:39 -0500
|
||||
Subject: [PATCH] Purpur: Add more logger output for invalid movement kicks
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 215eda414547bfdf662b4ea511fa3f774e125d94..7e10dca6450ca112db18a0ff03dbd2330a1d884a 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -813,6 +813,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
if (packet.getId() == this.awaitingTeleport) {
|
||||
if (this.awaitingPositionFromClient == null) {
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn("Disconnected on accept teleport packet. Was not expecting position data from client at this time"); // Purpur
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1374,8 +1375,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
@Override
|
||||
public void handleMovePlayer(ServerboundMovePlayerPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
|
||||
- if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) {
|
||||
+ // Purpur start
|
||||
+ boolean invalidX = Double.isNaN(packet.getX(0.0D));
|
||||
+ boolean invalidY = Double.isNaN(packet.getY(0.0D));
|
||||
+ boolean invalidZ = Double.isNaN(packet.getZ(0.0D));
|
||||
+ boolean invalidYaw = !Floats.isFinite(packet.getYRot(0.0F));
|
||||
+ boolean invalidPitch = !Floats.isFinite(packet.getXRot(0.0F));
|
||||
+ if (invalidX || invalidY || invalidZ || invalidYaw || invalidPitch) {
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
|
||||
+ ServerGamePacketListenerImpl.LOGGER.warn(String.format("Disconnected on move player packet. Invalid data: x=%b, y=%b, z=%b, yaw=%b, pitch=%b", invalidX, invalidY, invalidZ, invalidYaw, invalidPitch));
|
||||
+ // Purpur end
|
||||
} else {
|
||||
ServerLevel worldserver = this.player.getLevel();
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Thu, 24 Nov 2022 11:00:37 -0600
|
||||
Subject: [PATCH] Purpur: Log skipped entity's position
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
index 4f3708f5f5dcb6af8225bda1cc9204a6d974665f..6bdef01513cf86d6bf578ca37b364eab70f07843 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
@@ -576,6 +576,12 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
entity.load(nbt);
|
||||
}, () -> {
|
||||
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
|
||||
+ // Purpur start - log skipped entity's position
|
||||
+ try {
|
||||
+ ListTag pos = nbt.getList("Pos", 6);
|
||||
+ EntityType.LOGGER.warn("Location: {} {},{},{}", world.getWorld().getName(), pos.getDouble(0), pos.getDouble(1), pos.getDouble(2));
|
||||
+ } catch (Throwable ignore) {}
|
||||
+ // Purpur end
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Fri, 11 Oct 2019 00:17:39 -0500
|
||||
Subject: [PATCH] Purpur: Alternative Keepalive Handling
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 7e10dca6450ca112db18a0ff03dbd2330a1d884a..a3642fd721dbaad280df032007ec4412bc8f484d 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -260,6 +260,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
private long keepAliveTime = Util.getMillis();
|
||||
private boolean keepAlivePending;
|
||||
private long keepAliveChallenge;
|
||||
+ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur
|
||||
// CraftBukkit start - multithreaded fields
|
||||
private final AtomicInteger chatSpamTickCount = new AtomicInteger();
|
||||
private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits
|
||||
@@ -401,6 +402,21 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
long currentTime = Util.getMillis();
|
||||
long elapsedTime = currentTime - this.keepAliveTime;
|
||||
|
||||
+ // Purpur start
|
||||
+ if (org.dreeam.leaf.LeafConfig.useAlternateKeepAlive) {
|
||||
+ if (elapsedTime >= 1000L) { // 1 second
|
||||
+ if (!processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) {
|
||||
+ LOGGER.warn("{} was kicked due to keepalive timeout!", player.getName());
|
||||
+ disconnect(Component.translatable("disconnect.timeout"), 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
|
||||
@@ -3467,6 +3483,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
|
||||
@Override
|
||||
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||
+ // Purpur start
|
||||
+ if (org.dreeam.leaf.LeafConfig.useAlternateKeepAlive) {
|
||||
+ long id = packet.getId();
|
||||
+ if (keepAlives.size() > 0 && keepAlives.contains(id)) {
|
||||
+ int ping = (int) (Util.getMillis() - id);
|
||||
+ player.latency = (player.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.getLevel()); // CraftBukkit // Paper - This shouldn't be on the main thread
|
||||
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||
int i = (int) (Util.getMillis() - this.keepAliveTime);
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index f87f4f19738dfe8b58d3dbf0c27933fd3ec93883..9403774691cb83a3b916b4e0dc603385aceb4f4d 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -268,4 +268,9 @@ public class LeafConfig {
|
||||
private static void tileentitySetting() {
|
||||
persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames);
|
||||
}
|
||||
+
|
||||
+ public static boolean useAlternateKeepAlive = false;
|
||||
+ private static void useAlternateKeepAlive() {
|
||||
+ useAlternateKeepAlive = getBoolean("settings.use-alternate-keepalive", useAlternateKeepAlive);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Sat, 4 Apr 2020 03:07:59 -0500
|
||||
Subject: [PATCH] Purpur: Skip events if there's no listeners
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index 8ee8ff15f4511684261ff7a9417baa2ccd313b69..31e44f59bd34ae79dd1147263e446e6d6e9f8c66 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -429,6 +429,7 @@ public class Commands {
|
||||
private void runSync(ServerPlayer player, Collection<String> bukkit, RootCommandNode<SharedSuggestionProvider> rootcommandnode) {
|
||||
// Paper end - Async command map building
|
||||
new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper
|
||||
+ if (PlayerCommandSendEvent.getHandlerList().getRegisteredListeners().length > 0) { // Purpur - skip all this crap if there's nothing listening
|
||||
PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit));
|
||||
event.getPlayer().getServer().getPluginManager().callEvent(event);
|
||||
|
||||
@@ -439,6 +440,7 @@ public class Commands {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ } // Purpur - skip event
|
||||
player.connection.send(new ClientboundCommandsPacket(rootcommandnode));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 4 Jun 2021 09:13:54 -0500
|
||||
Subject: [PATCH] Purpur: Add toggle for sand duping fix
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
index 72f1866226269396ba0f0c1be269e237925d9322..fe813aea811d3b5c54978d33e7b766f7a9fd17ee 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
@@ -130,7 +130,7 @@ public class FallingBlockEntity extends Entity {
|
||||
@Override
|
||||
public void tick() {
|
||||
// Paper start - fix sand duping
|
||||
- if (this.isRemoved()) {
|
||||
+ if (org.dreeam.leaf.LeafConfig.fixSandDuping && this.isRemoved()) { // Purpur
|
||||
return;
|
||||
}
|
||||
// Paper end - fix sand duping
|
||||
@@ -147,7 +147,7 @@ public class FallingBlockEntity extends Entity {
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
|
||||
// Paper start - fix sand duping
|
||||
- if (this.isRemoved()) {
|
||||
+ if (org.dreeam.leaf.LeafConfig.fixSandDuping && this.isRemoved()) { // Purpur
|
||||
return;
|
||||
}
|
||||
// Paper end - fix sand duping
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 9403774691cb83a3b916b4e0dc603385aceb4f4d..1a2c32e6589de7705af26623a0c6badb9504324f 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -273,4 +273,9 @@ public class LeafConfig {
|
||||
private static void useAlternateKeepAlive() {
|
||||
useAlternateKeepAlive = getBoolean("settings.use-alternate-keepalive", useAlternateKeepAlive);
|
||||
}
|
||||
+
|
||||
+ public static boolean fixSandDuping = true;
|
||||
+ private static void sandSettings() {
|
||||
+ fixSandDuping = getBoolean("blocks.sand.fix-duping", fixSandDuping);
|
||||
+ }
|
||||
}
|
||||
129
patches/server/0025-Purpur-Lobotomize-stuck-villagers.patch
Normal file
129
patches/server/0025-Purpur-Lobotomize-stuck-villagers.patch
Normal file
@@ -0,0 +1,129 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Thu, 3 Dec 2020 17:56:18 -0600
|
||||
Subject: [PATCH] Purpur: Lobotomize stuck villagers
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
index 76a9da8209d557b913c49ccd281bf147b9ac4fa4..a39d038b5198c9244e2225e0fe383f3c96b49a08 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -139,6 +139,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
}, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> {
|
||||
return holder.is(PoiTypes.MEETING);
|
||||
});
|
||||
+ private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur
|
||||
+ private int notLobotomizedCount = 0; // Purpur
|
||||
|
||||
public long nextGolemPanic = -1; // Pufferfish
|
||||
|
||||
@@ -155,6 +157,47 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
this.setVillagerData(this.getVillagerData().setType(type).setProfession(VillagerProfession.NONE));
|
||||
}
|
||||
|
||||
+ private boolean checkLobotomized() {
|
||||
+ int interval = org.dreeam.leaf.LeafConfig.villagerLobotomizeCheckInterval;
|
||||
+ if (this.notLobotomizedCount > 3) {
|
||||
+ // check half as often if not lobotomized for the last 3+ consecutive checks
|
||||
+ interval *= 2;
|
||||
+ }
|
||||
+ if (this.level.getGameTime() % interval == 0) {
|
||||
+ // offset Y for short blocks like dirt_path/farmland
|
||||
+ this.isLobotomized = !canTravelFrom(new BlockPos(getX(), getY() + 0.0625D, getZ()));
|
||||
+
|
||||
+ if (this.isLobotomized) {
|
||||
+ this.notLobotomizedCount = 0;
|
||||
+ } else {
|
||||
+ this.notLobotomizedCount++;
|
||||
+ }
|
||||
+ }
|
||||
+ return this.isLobotomized;
|
||||
+ }
|
||||
+
|
||||
+ private boolean canTravelFrom(BlockPos pos) {
|
||||
+ return canTravelTo(pos.east()) || canTravelTo(pos.west()) || canTravelTo(pos.north()) || canTravelTo(pos.south());
|
||||
+ }
|
||||
+
|
||||
+ private boolean canTravelTo(BlockPos pos) {
|
||||
+ net.minecraft.world.level.block.state.BlockState state = this.level.getBlockStateIfLoaded(pos);
|
||||
+ if (state == null) {
|
||||
+ // chunk not loaded
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.world.level.block.Block bottom = state.getBlock();
|
||||
+ if (bottom instanceof net.minecraft.world.level.block.FenceBlock ||
|
||||
+ bottom instanceof net.minecraft.world.level.block.FenceGateBlock ||
|
||||
+ bottom instanceof net.minecraft.world.level.block.WallBlock) {
|
||||
+ // bottom block is too tall to get over
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.world.level.block.Block top = level.getBlockState(pos.above()).getBlock();
|
||||
+ // only if both blocks have no collision
|
||||
+ return !bottom.hasCollision && !top.hasCollision;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public Brain<Villager> getBrain() {
|
||||
return (Brain<Villager>) super.getBrain(); // CraftBukkit - decompile error
|
||||
@@ -250,12 +293,27 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
protected void customServerAiStep() { mobTick(false); }
|
||||
protected void mobTick(boolean inactive) {
|
||||
this.level.getProfiler().push("villagerBrain");
|
||||
+ // Purpur start
|
||||
+ if (org.dreeam.leaf.LeafConfig.villagerLobotomizeEnabled) {
|
||||
+ // treat as inactive if lobotomized
|
||||
+ inactive = inactive || checkLobotomized();
|
||||
+ } else {
|
||||
+ // clean up state for API
|
||||
+ this.isLobotomized = false;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
// Pufferfish start
|
||||
if (!inactive) {
|
||||
if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
|
||||
this.getBrain().tick((ServerLevel) this.level, this); // Paper
|
||||
}
|
||||
// Pufferfish end
|
||||
+ // Purpur start
|
||||
+ else if (this.isLobotomized && shouldRestock()) {
|
||||
+ // make sure we restock if needed when lobotomized
|
||||
+ restock();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
this.level.getProfiler().pop();
|
||||
if (this.assignProfessionWhenSpawned) {
|
||||
this.assignProfessionWhenSpawned = false;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
||||
index a1a8ac55e572156671e47317ba061855be79e5ac..ec3fb8865211bd7625103c37af7b96df37163a07 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
|
||||
@@ -222,4 +222,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
|
||||
getHandle().getGossips().gossips.clear();
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Purpur start
|
||||
+ @Override
|
||||
+ public boolean isLobotomized() {
|
||||
+ return getHandle().isLobotomized();
|
||||
+ }
|
||||
+ // Purpur end
|
||||
}
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index 1a2c32e6589de7705af26623a0c6badb9504324f..e3a2432c09871878c4c3981019d602a91fec3af7 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -278,4 +278,11 @@ public class LeafConfig {
|
||||
private static void sandSettings() {
|
||||
fixSandDuping = getBoolean("blocks.sand.fix-duping", fixSandDuping);
|
||||
}
|
||||
+
|
||||
+ public static boolean villagerLobotomizeEnabled = false;
|
||||
+ public static int villagerLobotomizeCheckInterval = 100;
|
||||
+ private static void villagerSettings() {
|
||||
+ villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
|
||||
+ villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Sun, 3 Jul 2022 04:13:57 -0500
|
||||
Subject: [PATCH] Purpur: Option to disable kick for out of order chat
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/PurpurMC/Purpur
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index a3642fd721dbaad280df032007ec4412bc8f484d..35afbe22475309f165fe8b540b51648ab41ed394 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2387,7 +2387,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
||||
do {
|
||||
instant1 = (Instant) this.lastChatTimeStamp.get();
|
||||
if (timestamp.isBefore(instant1)) {
|
||||
- return false;
|
||||
+ return !org.dreeam.leaf.LeafConfig.kickForOutOfOrderChat; // Purpur
|
||||
}
|
||||
} while (!this.lastChatTimeStamp.compareAndSet(instant1, timestamp));
|
||||
|
||||
diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
index e3a2432c09871878c4c3981019d602a91fec3af7..519770e60a1986e00b9754bb375b621cf084ec88 100644
|
||||
--- a/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
+++ b/src/main/java/org/dreeam/leaf/LeafConfig.java
|
||||
@@ -285,4 +285,9 @@ public class LeafConfig {
|
||||
villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
|
||||
villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
|
||||
}
|
||||
+
|
||||
+ public static boolean kickForOutOfOrderChat = true;
|
||||
+ private static void networkSettings() {
|
||||
+ kickForOutOfOrderChat = getBoolean("settings.network.kick-for-out-of-order-chat", kickForOutOfOrderChat);
|
||||
+ }
|
||||
}
|
||||
52
patches/server/0027-KeYi-Smarter-statistics-ticking.patch
Normal file
52
patches/server/0027-KeYi-Smarter-statistics-ticking.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mykyta Komarnytskyy <nkomarn@hotmail.com>
|
||||
Date: Sat, 24 Oct 2020 21:03:53 -0500
|
||||
Subject: [PATCH] KeYi: Smarter statistics ticking
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
In vanilla, statistics that count time spent for an action (i.e. time played or sneak time) are incremented every tick. This is retarded. With this patch and a configured interval of 20, the statistics are only ticked every 20th tick and are incremented by 20 ticks at a time. This means a lot less ticking with the same accurate counting.
|
||||
With an interval of 20, this patch saves roughly 3ms per tick on a server w/ 80 players online.
|
||||
|
||||
Original code by YatopiaMC, licensed under MIT
|
||||
You can find the original code on https://github.com/YatopiaMC/Yatopia
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
index 2e6557a19523d18aecff709de30cb4466b46a9fa..2ca483dea4eabd5f58076e5676e2ce4d0b1d9045 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||||
@@ -277,19 +277,21 @@ public abstract class Player extends LivingEntity {
|
||||
this.moveCloak();
|
||||
if (!this.level.isClientSide) {
|
||||
this.foodData.tick(this);
|
||||
- this.awardStat(Stats.PLAY_TIME);
|
||||
- this.awardStat(Stats.TOTAL_WORLD_TIME);
|
||||
- if (this.isAlive()) {
|
||||
- this.awardStat(Stats.TIME_SINCE_DEATH);
|
||||
- }
|
||||
-
|
||||
- if (this.isDiscrete()) {
|
||||
- this.awardStat(Stats.CROUCH_TIME);
|
||||
- }
|
||||
-
|
||||
- if (!this.isSleeping()) {
|
||||
- this.awardStat(Stats.TIME_SINCE_REST);
|
||||
+ // Mirai start
|
||||
+ if (tickCount % 20 == 0) {
|
||||
+ this.awardStat(Stats.PLAY_TIME, 20);
|
||||
+ this.awardStat(Stats.TOTAL_WORLD_TIME, 20);
|
||||
+ if (this.isAlive()) {
|
||||
+ this.awardStat(Stats.TIME_SINCE_DEATH, 20);
|
||||
+ }
|
||||
+ if (this.isDiscrete()) {
|
||||
+ this.awardStat(Stats.CROUCH_TIME, 20);
|
||||
+ }
|
||||
+ if (!this.isSleeping()) {
|
||||
+ this.awardStat(Stats.TIME_SINCE_REST, 20);
|
||||
+ }
|
||||
}
|
||||
+ // Mirai end
|
||||
}
|
||||
|
||||
int i = 29999999;
|
||||
38
patches/server/0028-KeYi-Fast-speed-check.patch
Normal file
38
patches/server/0028-KeYi-Fast-speed-check.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Sat, 22 Oct 2022 09:58:38 +0800
|
||||
Subject: [PATCH] KeYi: Fast speed check
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original code by NFT-Worlds, licensed under GNU General Public License v3.0
|
||||
You can find the original code on https://github.com/NFT-Worlds/Server
|
||||
|
||||
This patch was took from Mirai. (https://github.com/etil2jz/Mirai)
|
||||
|
||||
etil2jz's note:
|
||||
NFT-Worlds is related to Stellar devs, known for countless paid forks mostly taking open source patches,
|
||||
doing questionable/buggy ones, and claiming breathtaking performance improvements. Never ever pay for
|
||||
any of those Spigot forks!
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 37f1e4aa89da81fcae2d38bb741f3386950bdf51..0dec640d663defdd84b5a22a2668a20fde62d95c 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1193,7 +1193,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
this.tryCheckInsideBlocks();
|
||||
- float f2 = this.getBlockSpeedFactor();
|
||||
+ // KeYi start - Fast speed check
|
||||
+ float f2;
|
||||
+ if (this.getDeltaMovement().x == 0 && this.getDeltaMovement().z == 0) {
|
||||
+ f2 = 1;
|
||||
+ } else {
|
||||
+ f2 = this.getBlockSpeedFactor();
|
||||
+ }
|
||||
+ // KeYi end
|
||||
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply((double) f2, 1.0D, (double) f2));
|
||||
// Paper start - remove expensive streams from here
|
||||
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Mon, 24 Oct 2022 10:25:40 +0800
|
||||
Subject: [PATCH] KeYi: Do not save firework entities or the server may be
|
||||
laggy
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
index 5406925cd66f46ab8744123c670d72cea7bfc3a1..0b664dfef68b1e3905c9d8451602abf9cd9eafe6 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
@@ -358,4 +358,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
|
||||
public boolean isAttackable() {
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ // KeYi start
|
||||
+ @Override
|
||||
+ public boolean shouldBeSaved() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KeYi end
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: foss-mc <69294560+foss-mc@users.noreply.github.com>
|
||||
Date: Thu, 1 Jul 2021 12:17:44 +0000
|
||||
Subject: [PATCH] KeYi: Don't create new random instance
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original code by PatinaMC, licensed under GNU General Public License v3.0
|
||||
You can find the original code on https://github.com/PatinaMC/Patina
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 0ff21883cff37d1df7fda9b2cb93abcfd43f6482..cabed5594c2fb611d92d6319fe83259b8ca5bc21 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -395,7 +395,7 @@ public class ServerPlayer extends Player {
|
||||
long l = k * k;
|
||||
int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l;
|
||||
int j1 = this.getCoprime(i1);
|
||||
- int k1 = RandomSource.create().nextInt(i1);
|
||||
+ int k1 = worldserver.random.nextInt(i1); // Patina - don't create new random instance
|
||||
|
||||
for (int l1 = 0; l1 < i1; ++l1) {
|
||||
int i2 = (k1 + j1 * l1) % i1;
|
||||
@@ -432,7 +432,7 @@ public class ServerPlayer extends Player {
|
||||
long l = k * k;
|
||||
int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l;
|
||||
int j1 = this.getCoprime(i1);
|
||||
- int k1 = RandomSource.create().nextInt(i1);
|
||||
+ int k1 = world.random.nextInt(i1); // Patina - don't create new random instance
|
||||
|
||||
for (int l1 = 0; l1 < i1; ++l1) {
|
||||
int i2 = (k1 + j1 * l1) % i1;
|
||||
diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
|
||||
index 1ef089dbf83de35d875c00efdf468c397be56978..c345f10cbf7f3451edc604f97cdf959d70639e17 100644
|
||||
--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
|
||||
+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
|
||||
@@ -349,7 +349,7 @@ public class QueryThreadGs4 extends GenericThread {
|
||||
this.identBytes[2] = bs[5];
|
||||
this.identBytes[3] = bs[6];
|
||||
this.ident = new String(this.identBytes, StandardCharsets.UTF_8);
|
||||
- this.challenge = RandomSource.create().nextInt(16777216);
|
||||
+ this.challenge = java.util.concurrent.ThreadLocalRandom.current().nextInt(16777216); // Patina - don't create new random instance
|
||||
this.challengeBytes = String.format(Locale.ROOT, "\t%s%d\u0000", this.ident, this.challenge).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Mon, 24 Oct 2022 11:01:36 +0800
|
||||
Subject: [PATCH] KeYi: Skip entity move if no movement
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Copyright (c) 2021-2022 ishland
|
||||
|
||||
Original code by RelativityMC, licensed under MIT
|
||||
You can find the original code on https://github.com/RelativityMC/VMP-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 0dec640d663defdd84b5a22a2668a20fde62d95c..a88b54d2dbae6951d475ca11eddd444e25c178ad 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -397,6 +397,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
@javax.annotation.Nullable
|
||||
private UUID originWorld;
|
||||
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
|
||||
+ private boolean boundingBoxChanged = false; // KeYi
|
||||
|
||||
public void setOrigin(@javax.annotation.Nonnull Location location) {
|
||||
this.origin = location.toVector();
|
||||
@@ -1033,6 +1034,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
// Paper end - detailed watchdog information
|
||||
|
||||
public void move(MoverType movementType, Vec3 movement) {
|
||||
+ // KeYi start
|
||||
+ if (!boundingBoxChanged && movement.equals(Vec3.ZERO)) {
|
||||
+ boundingBoxChanged = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ // KeYi end
|
||||
+
|
||||
// Paper start - detailed watchdog information
|
||||
io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main");
|
||||
synchronized (this.posLock) {
|
||||
@@ -3814,6 +3822,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||
}
|
||||
|
||||
public final void setBoundingBox(AABB boundingBox) {
|
||||
+ if (!this.bb.equals(boundingBox)) boundingBoxChanged = true; // KeYi
|
||||
// CraftBukkit start - block invalid bounding boxes
|
||||
double minX = boundingBox.minX,
|
||||
minY = boundingBox.minY,
|
||||
126
patches/server/0032-KeYi-Optimized-getBiome-method.patch
Normal file
126
patches/server/0032-KeYi-Optimized-getBiome-method.patch
Normal file
@@ -0,0 +1,126 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Tue, 25 Oct 2022 00:28:35 +0800
|
||||
Subject: [PATCH] KeYi: Optimized getBiome method
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/fxmorin/carpet-fixes
|
||||
|
||||
Optimized the getBiome call to be 25% - 75% faster
|
||||
This is a fully vanilla optimization.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java
|
||||
index 5695c5116c8a338b2e41aafcb2dc9f2146856970..aa65785ac89a876111e5f661e0b1db6650010475 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java
|
||||
@@ -14,6 +14,7 @@ public class BiomeManager {
|
||||
private static final int ZOOM_MASK = 3;
|
||||
private final BiomeManager.NoiseBiomeSource noiseBiomeSource;
|
||||
private final long biomeZoomSeed;
|
||||
+ private static final double maxOffset = 0.4500000001D; // KeYi
|
||||
|
||||
public BiomeManager(BiomeManager.NoiseBiomeSource storage, long seed) {
|
||||
this.noiseBiomeSource = storage;
|
||||
@@ -29,39 +30,68 @@ public class BiomeManager {
|
||||
}
|
||||
|
||||
public Holder<Biome> getBiome(BlockPos pos) {
|
||||
- int i = pos.getX() - 2;
|
||||
- int j = pos.getY() - 2;
|
||||
- int k = pos.getZ() - 2;
|
||||
- int l = i >> 2;
|
||||
- int m = j >> 2;
|
||||
- int n = k >> 2;
|
||||
- double d = (double)(i & 3) / 4.0D;
|
||||
- double e = (double)(j & 3) / 4.0D;
|
||||
- double f = (double)(k & 3) / 4.0D;
|
||||
- int o = 0;
|
||||
- double g = Double.POSITIVE_INFINITY;
|
||||
-
|
||||
- for(int p = 0; p < 8; ++p) {
|
||||
- boolean bl = (p & 4) == 0;
|
||||
- boolean bl2 = (p & 2) == 0;
|
||||
- boolean bl3 = (p & 1) == 0;
|
||||
- int q = bl ? l : l + 1;
|
||||
- int r = bl2 ? m : m + 1;
|
||||
- int s = bl3 ? n : n + 1;
|
||||
- double h = bl ? d : d - 1.0D;
|
||||
- double t = bl2 ? e : e - 1.0D;
|
||||
- double u = bl3 ? f : f - 1.0D;
|
||||
- double v = getFiddledDistance(this.biomeZoomSeed, q, r, s, h, t, u);
|
||||
- if (g > v) {
|
||||
- o = p;
|
||||
- g = v;
|
||||
+ // KeYi
|
||||
+ int xMinus2 = pos.getX() - 2;
|
||||
+ int yMinus2 = pos.getY() - 2;
|
||||
+ int zMinus2 = pos.getZ() - 2;
|
||||
+ int x = xMinus2 >> 2; // BlockPos to BiomePos
|
||||
+ int y = yMinus2 >> 2;
|
||||
+ int z = zMinus2 >> 2;
|
||||
+ double quartX = (double) (xMinus2 & 3) / 4.0D; // quartLocal divided by 4
|
||||
+ double quartY = (double) (yMinus2 & 3) / 4.0D; // 0/4, 1/4, 2/4, 3/4
|
||||
+ double quartZ = (double) (zMinus2 & 3) / 4.0D; // [0, 0.25, 0.5, 0.75]
|
||||
+ int smallestX = 0;
|
||||
+ double smallestDist = Double.POSITIVE_INFINITY;
|
||||
+ for (int biomeX = 0; biomeX < 8; ++biomeX) {
|
||||
+ boolean everyOtherQuad = (biomeX & 4) == 0; // 1 1 1 1 0 0 0 0
|
||||
+ boolean everyOtherPair = (biomeX & 2) == 0; // 1 1 0 0 1 1 0 0
|
||||
+ boolean everyOther = (biomeX & 1) == 0; // 1 0 1 0 1 0 1 0
|
||||
+ double quartXX = everyOtherQuad ? quartX : quartX - 1.0D; //[-1.0,-0.75,-0.5,-0.25,0.0,0.25,0.5,0.75]
|
||||
+ double quartYY = everyOtherPair ? quartY : quartY - 1.0D;
|
||||
+ double quartZZ = everyOther ? quartZ : quartZ - 1.0D;
|
||||
+
|
||||
+ //This code block is new
|
||||
+ double maxQuartYY = 0.0D, maxQuartZZ = 0.0D;
|
||||
+ if (biomeX != 0) {
|
||||
+ maxQuartYY = Mth.square(Math.max(quartYY + maxOffset, Math.abs(quartYY - maxOffset)));
|
||||
+ maxQuartZZ = Mth.square(Math.max(quartZZ + maxOffset, Math.abs(quartZZ - maxOffset)));
|
||||
+ double maxQuartXX = Mth.square(Math.max(quartXX + maxOffset, Math.abs(quartXX - maxOffset)));
|
||||
+ if (smallestDist < maxQuartXX + maxQuartYY + maxQuartZZ) continue;
|
||||
}
|
||||
- }
|
||||
|
||||
- int w = (o & 4) == 0 ? l : l + 1;
|
||||
- int x = (o & 2) == 0 ? m : m + 1;
|
||||
- int y = (o & 1) == 0 ? n : n + 1;
|
||||
- return this.noiseBiomeSource.getNoiseBiome(w, x, y);
|
||||
+ int xx = everyOtherQuad ? x : x + 1;
|
||||
+ int yy = everyOtherPair ? y : y + 1;
|
||||
+ int zz = everyOther ? z : z + 1;
|
||||
+
|
||||
+ //I transferred the code from method_38106 to here, so I could call continue halfway through
|
||||
+ long seed = LinearCongruentialGenerator.next(this.biomeZoomSeed, xx);
|
||||
+ seed = LinearCongruentialGenerator.next(seed, yy);
|
||||
+ seed = LinearCongruentialGenerator.next(seed, zz);
|
||||
+ seed = LinearCongruentialGenerator.next(seed, xx);
|
||||
+ seed = LinearCongruentialGenerator.next(seed, yy);
|
||||
+ seed = LinearCongruentialGenerator.next(seed, zz);
|
||||
+ double offsetX = getFiddle(seed);
|
||||
+ double sqrX = Mth.square(quartXX + offsetX);
|
||||
+ if (biomeX != 0 && smallestDist < sqrX + maxQuartYY + maxQuartZZ) continue; //skip the rest of the loop
|
||||
+ seed = LinearCongruentialGenerator.next(seed, this.biomeZoomSeed);
|
||||
+ double offsetY = getFiddle(seed);
|
||||
+ double sqrY = Mth.square(quartYY + offsetY);
|
||||
+ if (biomeX != 0 && smallestDist < sqrX + sqrY + maxQuartZZ) continue; // skip the rest of the loop
|
||||
+ seed = LinearCongruentialGenerator.next(seed, this.biomeZoomSeed);
|
||||
+ double offsetZ = getFiddle(seed);
|
||||
+ double biomeDist = sqrX + sqrY + Mth.square(quartZZ + offsetZ);
|
||||
+
|
||||
+ if (smallestDist > biomeDist) {
|
||||
+ smallestX = biomeX;
|
||||
+ smallestDist = biomeDist;
|
||||
+ }
|
||||
+ }
|
||||
+ return this.noiseBiomeSource.getNoiseBiome(
|
||||
+ (smallestX & 4) == 0 ? x : x + 1,
|
||||
+ (smallestX & 2) == 0 ? y : y + 1,
|
||||
+ (smallestX & 1) == 0 ? z : z + 1
|
||||
+ );
|
||||
+ // KeYi end
|
||||
}
|
||||
|
||||
public Holder<Biome> getNoiseBiomeAtPosition(double x, double y, double z) {
|
||||
87
patches/server/0033-KeYi-Use-optimized-RecipeManager.patch
Normal file
87
patches/server/0033-KeYi-Use-optimized-RecipeManager.patch
Normal file
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Tue, 25 Oct 2022 00:57:45 +0800
|
||||
Subject: [PATCH] KeYi: Use optimized RecipeManager
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/fxmorin/carpet-fixes
|
||||
|
||||
Optimized the RecipeManager getFirstMatch call to be up to 3x faster
|
||||
This is a fully vanilla optimization. Improves: [Blast]Furnace/Campfire/Smoker/Stonecutter/Crafting/Sheep Color Choosing
|
||||
This was mostly made for the auto crafting table, since the performance boost is much more visible while using that mod
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
index 2f712bfc1f717ba410bf34669d7b0a919ca218cc..fa7f4c3e14aa4ec11187f7c0f96cb4504ee38547 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
@@ -11,14 +11,7 @@ import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.logging.LogUtils;
|
||||
-import java.util.Collection;
|
||||
-import java.util.Collections;
|
||||
-import java.util.Comparator;
|
||||
-import java.util.Iterator;
|
||||
-import java.util.List;
|
||||
-import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
-import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -33,6 +26,7 @@ import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.slf4j.Logger;
|
||||
+import java.util.*; // KeYi
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; // CraftBukkit
|
||||
|
||||
@@ -103,13 +97,28 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
|
||||
}
|
||||
|
||||
public <C extends Container, T extends Recipe<C>> Optional<T> getRecipeFor(RecipeType<T> type, C inventory, Level world) {
|
||||
- // CraftBukkit start
|
||||
- Optional<T> recipe = this.byType(type).values().stream().filter((irecipe) -> {
|
||||
- return irecipe.matches(inventory, world);
|
||||
- }).findFirst();
|
||||
- inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found
|
||||
- // CraftBukkit end
|
||||
- return recipe;
|
||||
+ // KeYi start
|
||||
+ int slots = 0;
|
||||
+ int count;
|
||||
+ //compare size to quickly remove recipes that are not even close. Plus remove streams
|
||||
+ for (int slot = 0; slot < inventory.getContainerSize(); slot++)
|
||||
+ if (!inventory.getItem(slot).isEmpty()) slots++;
|
||||
+ for (Recipe<C> recipe : this.byType(type).values()) {
|
||||
+ count = 0;
|
||||
+ if (recipe instanceof CustomRecipe) {
|
||||
+ if (recipe.matches(inventory, world)) {
|
||||
+ return (Optional<T>) Optional.of(recipe);
|
||||
+ }
|
||||
+ } else {
|
||||
+ for (Ingredient ingredient : recipe.getIngredients())
|
||||
+ if (ingredient != Ingredient.EMPTY) count++;
|
||||
+ if (count == slots && recipe.matches(inventory, world)) {
|
||||
+ return (Optional<T>) Optional.of(recipe);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ // KeYi end
|
||||
}
|
||||
|
||||
public <C extends Container, T extends Recipe<C>> Optional<Pair<ResourceLocation, T>> getRecipeFor(RecipeType<T> type, C inventory, Level world, @Nullable ResourceLocation id) {
|
||||
@@ -131,7 +140,7 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
|
||||
}
|
||||
|
||||
public <C extends Container, T extends Recipe<C>> List<T> getAllRecipesFor(RecipeType<T> type) {
|
||||
- return List.copyOf(this.byType(type).values());
|
||||
+ return new ArrayList<>(this.byType(type).values()); // KeYi
|
||||
}
|
||||
|
||||
public <C extends Container, T extends Recipe<C>> List<T> getRecipesFor(RecipeType<T> type, C inventory, Level world) {
|
||||
@@ -0,0 +1,530 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Fri, 18 Nov 2022 23:39:13 +0800
|
||||
Subject: [PATCH] KeYi: Use a faster random implementation
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
diff --git a/src/main/java/cc/keyimc/keyi/utils/FastRandom.java b/src/main/java/cc/keyimc/keyi/utils/FastRandom.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a9b3a467e7dbfdc78c11f04e6bb5a9642c20470c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/cc/keyimc/keyi/utils/FastRandom.java
|
||||
@@ -0,0 +1,395 @@
|
||||
+/**
|
||||
+ * This is a faster implementation of java.util.Random.
|
||||
+ * Code from https://gist.github.com/Xyene/4637619
|
||||
+ * Licensed under GNU Lesser General Public License v3.0
|
||||
+ * <p>
|
||||
+ * A random number generator based on the simple and fast xor-shift pseudo
|
||||
+ * random number generator (RNG) specified in:
|
||||
+ * Marsaglia, George. (2003). Xorshift RNGs.
|
||||
+ * http://www.jstatsoft.org/v08/i14/xorshift.pdf
|
||||
+ * Translated from:
|
||||
+ * http://www.codeproject.com/Articles/9187/A-fast-equivalent-for-System-Random.
|
||||
+ */
|
||||
+
|
||||
+package cc.keyimc.keyi.utils;
|
||||
+
|
||||
+@SuppressWarnings("SuspiciousNameCombination")
|
||||
+public class FastRandom extends java.util.Random {
|
||||
+ final double REAL_UNIT_INT = 1.0 / (0x7FFFFFFFL);
|
||||
+ final double REAL_UNIT_UINT = 1.0 / (0xFFFFFFFFL);
|
||||
+ final long Y = 842502087L, Z = 3579807591L, W = 273326509L;
|
||||
+ long x, y, z, w;
|
||||
+
|
||||
+ public FastRandom() {
|
||||
+ seed((int) System.currentTimeMillis());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSeed(long seed) {
|
||||
+ seed((int) seed);
|
||||
+ }
|
||||
+
|
||||
+ public void seed(int seed) {
|
||||
+ // The only stipulation stated for the xorshift RNG is that at least one of
|
||||
+ // the seeds x,y,z,w is non-zero. We fulfill that requirement by only allowing
|
||||
+ // resetting of the x seed
|
||||
+ x = seed;
|
||||
+ y = Y;
|
||||
+ z = Z;
|
||||
+ w = W;
|
||||
+ }
|
||||
+
|
||||
+ long boolBuffer;
|
||||
+ int boolBufferBits = 0;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean nextBoolean() {
|
||||
+ if (boolBufferBits == 0) {
|
||||
+ boolBuffer = nextUInt();
|
||||
+ boolBufferBits = 32;
|
||||
+ }
|
||||
+ boolBuffer >>= 1;
|
||||
+ boolean bit = (boolBuffer & 1) == 0;
|
||||
+ --boolBufferBits;
|
||||
+ return bit;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void nextBytes(byte[] buffer) {
|
||||
+ // Fill up the bulk of the buffer in chunks of 4 bytes at a time.
|
||||
+ long x = this.x, y = this.y, z = this.z, w = this.w;
|
||||
+ int i = 0;
|
||||
+ long t;
|
||||
+ for (int bound = buffer.length - 3; i < bound; ) {
|
||||
+ // Generate 4 bytes.
|
||||
+ // Increased performance is achieved by generating 4 random bytes per loop.
|
||||
+ // Also note that no mask needs to be applied to zero out the higher order bytes before
|
||||
+ // casting because the cast ignores thos bytes. Thanks to Stefan Trosch黷z for pointing this out.
|
||||
+ t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+ w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
|
||||
+
|
||||
+ buffer[i++] = (byte) w;
|
||||
+ buffer[i++] = (byte) (w >> 8);
|
||||
+ buffer[i++] = (byte) (w >> 16);
|
||||
+ buffer[i++] = (byte) (w >> 24);
|
||||
+ }
|
||||
+
|
||||
+ // Fill up any remaining bytes in the buffer.
|
||||
+ if (i < buffer.length) {
|
||||
+ // Generate 4 bytes.
|
||||
+ t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+ w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
|
||||
+
|
||||
+ buffer[i++] = (byte) w;
|
||||
+ if (i < buffer.length) {
|
||||
+ buffer[i++] = (byte) (w >> 8);
|
||||
+ if (i < buffer.length) {
|
||||
+ buffer[i++] = (byte) (w >> 16);
|
||||
+ if (i < buffer.length) {
|
||||
+ buffer[i] = (byte) (w >> 24);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ this.x = x;
|
||||
+ this.y = y;
|
||||
+ this.z = z;
|
||||
+ this.w = w;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double nextDouble() {
|
||||
+ long t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+
|
||||
+ // Here we can gain a 2x speed improvement by generating a value that can be cast to
|
||||
+ // an int instead of the more easily available uint. If we then explicitly cast to an
|
||||
+ // int the compiler will then cast the int to a double to perform the multiplication,
|
||||
+ // this final cast is a lot faster than casting from a uint to a double. The extra cast
|
||||
+ // to an int is very fast (the allocated bits remain the same) and so the overall effect
|
||||
+ // of the extra cast is a significant performance improvement.
|
||||
+ //
|
||||
+ // Also note that the loss of one bit of precision is equivalent to what occurs within
|
||||
+ // System.Random.
|
||||
+ return (REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))));
|
||||
+ }
|
||||
+
|
||||
+ public double random() {
|
||||
+ return nextDouble();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float nextFloat() {
|
||||
+ return (float) nextDouble();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt() {
|
||||
+ long t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+ return (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt(int upperBound) {
|
||||
+ if (upperBound < 0)
|
||||
+ throw new IllegalArgumentException("upperBound must be >=0");
|
||||
+
|
||||
+ long t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+
|
||||
+ return (int) ((REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * upperBound);
|
||||
+ }
|
||||
+
|
||||
+ public int nextInt(int lowerBound, int upperBound) {
|
||||
+ if (lowerBound > upperBound)
|
||||
+ throw new IllegalArgumentException("upperBound must be >=lowerBound");
|
||||
+
|
||||
+ long t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+
|
||||
+ // The explicit int cast before the first multiplication gives better performance.
|
||||
+ // See comments in NextDouble.
|
||||
+ int range = upperBound - lowerBound;
|
||||
+ if (range < 0) {
|
||||
+ // If range is <0 then an overflow has occured and must resort to using long integer arithmetic instead (slower).
|
||||
+ // We also must use all 32 bits of precision, instead of the normal 31, which again is slower.
|
||||
+ return lowerBound + (int) ((REAL_UNIT_UINT * (double) (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))) * (double) ((long) upperBound - (long) lowerBound));
|
||||
+ }
|
||||
+ // 31 bits of precision will suffice if range<=int.MaxValue. This allows us to cast to an int and gain
|
||||
+ // a little more performance.
|
||||
+ return lowerBound + (int) ((REAL_UNIT_INT * (double) (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * (double) range);
|
||||
+ }
|
||||
+
|
||||
+ public long nextUInt() {
|
||||
+ long t = (x ^ (x << 11));
|
||||
+ x = y;
|
||||
+ y = z;
|
||||
+ z = w;
|
||||
+ return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))) & (0xFFFFFFFFL);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long nextLong() {
|
||||
+ return nextUInt() << 32 + nextUInt();
|
||||
+ }
|
||||
+
|
||||
+ double gaussNext;
|
||||
+ boolean hasGaussNext;
|
||||
+ final double TWOPI = Math.PI * 2;
|
||||
+
|
||||
+ /**
|
||||
+ * Get a random number in the range [min, max) or [min, max] depending on rounding.
|
||||
+ *
|
||||
+ * @param min Low bound
|
||||
+ * @param max High bound
|
||||
+ * @return A uniformly distributed double
|
||||
+ */
|
||||
+ public double uniform(double min, double max) {
|
||||
+ return min + (max - min) * nextDouble();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Triangular distribution.
|
||||
+ * <p/>
|
||||
+ * Continuous distribution bounded by given lower and upper limits,
|
||||
+ * and having a given mode value in-between.
|
||||
+ * http://en.wikipedia.org/wiki/Triangular_distribution
|
||||
+ *
|
||||
+ * @param low Low bound
|
||||
+ * @param high High bound
|
||||
+ * @param mode Mode
|
||||
+ * @return A number from the triangular distribution specified
|
||||
+ */
|
||||
+ public double triangular(int low, int high, int mode) {
|
||||
+ double u = nextDouble();
|
||||
+ double c = (mode - low) / (high - low);
|
||||
+ if (u > c) {
|
||||
+ u = 1.0 - u;
|
||||
+ c = 1.0 - c;
|
||||
+ int k = low;
|
||||
+ low = high;
|
||||
+ high = k;
|
||||
+ }
|
||||
+ return low + (high - low) * Math.sqrt(u * c);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gaussian distribution, mean is 0 and standard deviation is 1.
|
||||
+ * <p/>
|
||||
+ * mu is the mean, and sigma is the standard deviation.
|
||||
+ *
|
||||
+ * @return A double in Gaussian distribution
|
||||
+ */
|
||||
+ public double gauss() {
|
||||
+ return nextGaussian();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gaussian distribution, with user-specified mean and standard deviation.
|
||||
+ * <p/>
|
||||
+ * mu is the mean, and sigma is the standard deviation.
|
||||
+ *
|
||||
+ * @return A double in Gaussian distribution
|
||||
+ */
|
||||
+ public double gauss(double mu, double sigma) {
|
||||
+ return mu + sigma * nextGaussian();
|
||||
+ }
|
||||
+
|
||||
+ public double gaussUnsigned(double mu, double sigma) {
|
||||
+ double out = gauss(mu, sigma);
|
||||
+ return out > 1 ? out : 1;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Log normal distribution.
|
||||
+ * <p/>
|
||||
+ * If you take the natural logarithm of this distribution, you'll get a
|
||||
+ * normal distribution with mean mu and standard deviation sigma.
|
||||
+ * mu can have any value, and sigma must be greater than zero.
|
||||
+ *
|
||||
+ * @param mu Mean
|
||||
+ * @param sigma Standard deviation
|
||||
+ * @return A number from the log normal distribution specified
|
||||
+ */
|
||||
+ public double logNormal(double mu, double sigma) {
|
||||
+ return Math.exp(gauss(mu, sigma));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Exponential distribution.
|
||||
+ * <p/>
|
||||
+ * lambda is 1.0 divided by the desired mean. It should be
|
||||
+ * nonzero. Returned values range from 0 to positive infinity
|
||||
+ * if lambda is positive, and from negative infinity to 0
|
||||
+ * if lambda is negative.
|
||||
+ *
|
||||
+ * @param lambda A non-zero value
|
||||
+ */
|
||||
+ public double exponential(double lambda) {
|
||||
+ return -Math.log(1.0 - random()) / lambda;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Circular data distribution.
|
||||
+ * <p/>
|
||||
+ * If kappa is equal to zero, this distribution reduces
|
||||
+ * to a uniform random angle over the range 0 to 2*pi.
|
||||
+ *
|
||||
+ * @param mu the mean angle, expressed in radians between 0 and 2*pi.
|
||||
+ * @param kappa the concentration parameter, which must be greater than or
|
||||
+ * equal to zero.
|
||||
+ * @return A number from the circular data distribution specified
|
||||
+ */
|
||||
+ public double circularData(double mu, double kappa) {
|
||||
+ if (kappa <= 1e-6)
|
||||
+ return TWOPI * nextDouble();
|
||||
+
|
||||
+ double a = 1.0 + Math.sqrt(1.0 + 4.0 * kappa * kappa);
|
||||
+ double b = (a - Math.sqrt(2.0 * a)) / (2.0 * kappa);
|
||||
+ double r = (1.0 + b * b) / (2.0 * b);
|
||||
+ double u1, u2, u3, f, c, z, theta = 0;
|
||||
+
|
||||
+ while (true) {
|
||||
+ u1 = nextDouble();
|
||||
+
|
||||
+ z = Math.cos(Math.PI * u1);
|
||||
+ f = (1.0 + r * z) / (r + z);
|
||||
+ c = kappa * (r - f);
|
||||
+
|
||||
+ u2 = nextDouble();
|
||||
+
|
||||
+ if (u2 < c * (2.0 - c) || u2 <= c * Math.exp(1.0 - c))
|
||||
+ break;
|
||||
+
|
||||
+ u3 = nextDouble();
|
||||
+ if (u3 > 0.5)
|
||||
+ theta = (mu % TWOPI) + Math.acos(f);
|
||||
+ else
|
||||
+ theta = (mu % TWOPI) - Math.acos(f);
|
||||
+ }
|
||||
+ return theta;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ final double LOG4 = Math.log(4);
|
||||
+ final double SG_MAGICCONST = 1.0 + Math.log(4.5);
|
||||
+
|
||||
+ /**
|
||||
+ * Gamma distribution. Not the gamma function!
|
||||
+ * Conditions on the parameters are alpha > 0 and beta > 0.
|
||||
+ * <p/>
|
||||
+ * The probability distribution function is:
|
||||
+ * pdf(x) = (x ** (alpha - 1) * math.exp(-x / beta)) / (math.gamma(alpha) * beta ** alpha)
|
||||
+ *
|
||||
+ * @param alpha Alpha
|
||||
+ * @param beta Beta
|
||||
+ * @return A number from the gamma distribution specified
|
||||
+ */
|
||||
+ public double gamma(double alpha, double beta) {
|
||||
+ if (alpha <= 0.0 || beta <= 0.0)
|
||||
+ throw new IllegalArgumentException("alpha and beta must be > 0.0");
|
||||
+
|
||||
+ if (alpha > 1.0) {
|
||||
+ double ainv = Math.sqrt(2.0 * alpha - 1.0);
|
||||
+ double bbb = alpha - LOG4;
|
||||
+ double ccc = alpha + ainv;
|
||||
+ double u1, u2, v, x, z, r;
|
||||
+
|
||||
+ while (true) {
|
||||
+ u1 = random();
|
||||
+ if (!(1e-7 < u1 && u1 < .9999999))
|
||||
+ continue;
|
||||
+ u2 = 1.0 - random();
|
||||
+ v = Math.log(u1 / (1.0 - u1)) / ainv;
|
||||
+ x = alpha * Math.exp(v);
|
||||
+ z = u1 * u1 * u2;
|
||||
+ r = bbb + ccc * v - x;
|
||||
+ if (r + SG_MAGICCONST - 4.5 * z >= 0.0 || r >= Math.log(z))
|
||||
+ return x * beta;
|
||||
+ }
|
||||
+ } else if (alpha == 1.0) {
|
||||
+ // exponential(1)
|
||||
+ double u;
|
||||
+ u = random();
|
||||
+ while (u <= 1e-7)
|
||||
+ u = random();
|
||||
+ return -Math.log(u) * beta;
|
||||
+ } else {
|
||||
+ // alpha is between 0 and 1 (exclusive)
|
||||
+ // Uses ALGORITHM GS of Statistical Computing -Kennedy & Gentle
|
||||
+
|
||||
+ double u, b, p, x, u1;
|
||||
+ while (true) {
|
||||
+ u = random();
|
||||
+ b = (Math.E + alpha) / Math.E;
|
||||
+ p = b * u;
|
||||
+ if (p <= 1.0)
|
||||
+ x = Math.pow(p, (1.0 / alpha));
|
||||
+ else
|
||||
+ x = -Math.log((b - p) / alpha);
|
||||
+ u1 = random();
|
||||
+ if (p > 1.0) {
|
||||
+ if (u1 <= Math.pow(x, (alpha - 1.0)))
|
||||
+ break;
|
||||
+ } else if (u1 <= Math.exp(-x))
|
||||
+ break;
|
||||
+ }
|
||||
+ return x * beta;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
||||
index e5ea9f27a1936ed9e329e74317c91c5df89b9fbd..89a41d396162a1c2eb2df5192b0d888b08fec6ec 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
||||
@@ -10,10 +10,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
+import cc.keyimc.keyi.utils.FastRandom; // KeYi
|
||||
|
||||
public class PaperLootableInventoryData {
|
||||
|
||||
- private static final Random RANDOM = new Random();
|
||||
+ private static final Random RANDOM = new FastRandom(); // KeYi - use a faster random
|
||||
|
||||
private long lastFill = -1;
|
||||
private long nextRefill = -1;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index de7a5f3812a017131fd1b32fbeff10e325b1cd2e..ebe2c0b17fc6e21a5ced4f35b594d466f9f573f5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -53,6 +53,10 @@ import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.ticks.LevelChunkTicks;
|
||||
import net.minecraft.world.ticks.TickContainerAccess;
|
||||
import org.slf4j.Logger;
|
||||
+// KeYi start
|
||||
+import cc.keyimc.keyi.utils.FastRandom;
|
||||
+import java.util.Random; // KeYi
|
||||
+// KeYi end
|
||||
|
||||
public class LevelChunk extends ChunkAccess {
|
||||
|
||||
@@ -932,7 +936,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
if (this.needsDecoration) {
|
||||
try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper
|
||||
this.needsDecoration = false;
|
||||
- java.util.Random random = new java.util.Random();
|
||||
+ Random random = new FastRandom();
|
||||
random.setSeed(this.level.getSeed());
|
||||
long xRand = random.nextLong() / 2L * 2L + 1L;
|
||||
long zRand = random.nextLong() / 2L * 2L + 1L;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index dcfe090c269d4cbcc2eb1b6f85392848bb34656c..ef8909c9c13c8f46ec6d452f0d14c9a1119e0edf 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.slf4j.Logger;
|
||||
+import cc.keyimc.keyi.utils.FastRandom; // KeYi
|
||||
|
||||
public class RegionFile implements AutoCloseable {
|
||||
|
||||
@@ -109,7 +110,7 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
|
||||
private void backupRegionFile() {
|
||||
- Path backup = this.regionFile.getParent().resolve(this.regionFile.getFileName() + "." + new java.util.Random().nextLong() + ".backup");
|
||||
+ Path backup = this.regionFile.getParent().resolve(this.regionFile.getFileName() + "." + new FastRandom().nextLong() + ".backup"); // KeYi - use a faster random
|
||||
this.backupRegionFile(backup);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index f8d321e925bf2708e51590542325c1bdc67d5964..ace7e9f66c3583fc51f06bd9963ed55968d40c0f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -134,6 +134,7 @@ import org.bukkit.util.Consumer;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.StructureSearchResult;
|
||||
import org.bukkit.util.Vector;
|
||||
+import cc.keyimc.keyi.utils.FastRandom; // KeYi
|
||||
|
||||
public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
public static final int CUSTOM_DIMENSION_OFFSET = 10;
|
||||
@@ -226,7 +227,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
- private static final Random rand = new Random();
|
||||
+ private static final Random rand = new FastRandom(); // KeYi - use a faster random
|
||||
|
||||
public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) {
|
||||
this.world = world;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
index d1c7ab67cba881d96b7a5e9220130d86d0514304..309d1ce15aace9da4a84819e8511af2cc12b1ea8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
||||
@@ -12,10 +12,11 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
+import cc.keyimc.keyi.utils.FastRandom; // KeYi
|
||||
|
||||
public class CraftFirework extends CraftProjectile implements Firework {
|
||||
|
||||
- private final Random random = new Random();
|
||||
+ private final Random random = new FastRandom(); // KeYi - use a faster random
|
||||
//private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
|
||||
|
||||
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
index a9673a804d597599c35c83f4f245510c83005328..08d47eee550e2e9ddfb4dc0ce12945401b16c23c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
@@ -42,13 +42,14 @@ import org.bukkit.craftbukkit.util.RandomSourceWrapper;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
+import cc.keyimc.keyi.utils.FastRandom; // KeYi
|
||||
|
||||
public class CustomChunkGenerator extends InternalChunkGenerator {
|
||||
|
||||
private final net.minecraft.world.level.chunk.ChunkGenerator delegate;
|
||||
private final ChunkGenerator generator;
|
||||
private final ServerLevel world;
|
||||
- private final Random random = new Random();
|
||||
+ private final Random random = new FastRandom(); // KeYi - use a faster random
|
||||
private boolean newApi;
|
||||
private boolean implementBaseHeight = true;
|
||||
|
||||
59
patches/server/0035-KeYi-Player-Skull-API.patch
Normal file
59
patches/server/0035-KeYi-Player-Skull-API.patch
Normal file
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalgic853 <yuu8583@proton.me>
|
||||
Date: Sun, 20 Nov 2022 00:20:00 +0800
|
||||
Subject: [PATCH] KeYi: Player Skull API
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 99bf1485ddecb5fc88850242e9c32850781c4b36..0813237d69ad1a9d4ed32772803fb5111a015dd4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -26,6 +26,9 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
+import java.util.concurrent.CompletableFuture;
|
||||
+import java.util.concurrent.ExecutorService;
|
||||
+import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -146,6 +149,7 @@ import org.bukkit.event.player.PlayerUnregisterChannelEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.InventoryView.Property;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
+import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.map.MapCursor;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
@@ -3003,4 +3007,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
return this.spigot;
|
||||
}
|
||||
// Spigot end
|
||||
+
|
||||
+ // KeYi start
|
||||
+ @Override
|
||||
+ public ItemStack getSkull() {
|
||||
+ ItemStack skull = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
+ SkullMeta meta = (SkullMeta) skull.getItemMeta();
|
||||
+
|
||||
+ meta.setOwningPlayer(this);
|
||||
+
|
||||
+ skull.setItemMeta(meta);
|
||||
+
|
||||
+ return skull;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CompletableFuture<ItemStack> getSkullAsynchronously() {
|
||||
+ ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
+
|
||||
+ CompletableFuture<ItemStack> future = (CompletableFuture<ItemStack>) executorService.submit(() -> getSkull());
|
||||
+ executorService.shutdown();
|
||||
+
|
||||
+ return future;
|
||||
+ }
|
||||
+ // KeYi end
|
||||
}
|
||||
31
patches/server/0036-KeYi-Reduce-sensor-work.patch
Normal file
31
patches/server/0036-KeYi-Reduce-sensor-work.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: peaches94 <peachescu94@gmail.com>
|
||||
Date: Sun, 10 Jul 2022 15:44:38 -0500
|
||||
Subject: [PATCH] KeYi: Reduce sensor work
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/KeYiMC/KeYi
|
||||
|
||||
Original code by Bloom-host, licensed under GNU General Public License v3.0
|
||||
You can find the original code on https://github.com/Bloom-host/Petal
|
||||
|
||||
this patch is focused around the sensors used for ai
|
||||
delete the line of sight cache less often and use a faster nearby comparison
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
index 94b45579dc371ee980565aed2f5dee78ebd44427..48746d84f18cc8ee2f57785c65a5659ced454d39 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
|
||||
@@ -873,10 +873,10 @@ public abstract class Mob extends LivingEntity {
|
||||
return;
|
||||
}
|
||||
// Paper end
|
||||
+ int i = this.level.getServer().getTickCount() + this.getId(); // petal - move up
|
||||
this.level.getProfiler().push("sensing");
|
||||
- this.sensing.tick();
|
||||
+ if (i % 10 == 0) this.sensing.tick(); // petal - only refresh line of sight cache every half second
|
||||
this.level.getProfiler().pop();
|
||||
- int i = this.level.getServer().getTickCount() + this.getId();
|
||||
|
||||
if (i % 2 != 0 && this.tickCount > 1) {
|
||||
this.level.getProfiler().push("targetSelector");
|
||||
15
settings.gradle.kts
Normal file
15
settings.gradle.kts
Normal file
@@ -0,0 +1,15 @@
|
||||
import java.util.Locale
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "leaf"
|
||||
for (name in listOf("Leaf-API", "Leaf-Server")) {
|
||||
val projName = name.toLowerCase(Locale.ENGLISH)
|
||||
include(projName)
|
||||
findProject(":$projName")!!.projectDir = file(name)
|
||||
}
|
||||
Reference in New Issue
Block a user