Merge branch 'ver/1.21.4' into feat/quiver-bundle

This commit is contained in:
granny
2025-01-30 12:20:21 -08:00
772 changed files with 33474 additions and 45822 deletions

View File

@@ -29,9 +29,16 @@ ij_java_names_count_to_use_import_on_demand = 999999
ij_java_imports_layout = *,|,$* ij_java_imports_layout = *,|,$*
ij_java_generate_final_locals = true ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true ij_java_generate_final_parameters = true
ij_java_method_parameters_new_line_after_left_paren = true
[test-plugin/**/*.java] ij_java_method_parameters_right_paren_on_new_line = true
ij_java_use_fq_class_names = false ij_java_use_fq_class_names = false
ij_java_class_names_in_javadoc = 1
[Purpur-Server/src/main/resources/data/**/*.json] [purpur-server/src/minecraft/java/**/*.java]
ij_java_use_fq_class_names = true
[purpur-server/src/minecraft/resources/data/**/*.json]
indent_size = 2 indent_size = 2
[paper-api/src/generated/**/*.java]
ij_java_imports_layout = $*,|,*

View File

@@ -17,17 +17,16 @@ jobs:
distribution: temurin distribution: temurin
java-version: 21 java-version: 21
cache: 'gradle' cache: 'gradle'
- uses: gradle/wrapper-validation-action@v2 - uses: gradle/actions/setup-gradle@v4
- uses: gradle/actions/setup-gradle@v3
- name: Configure Git - name: Configure Git
run: git config --global user.email "no-reply@github.com" && git config --global user.name "Github Actions" run: git config --global user.email "no-reply@github.com" && git config --global user.name "Github Actions"
- name: Apply Patches - name: Apply Patches
run: ./gradlew applyPatches --no-daemon --stacktrace run: ./gradlew applyAllPatches --no-daemon --stacktrace
- name: Build - name: Build
run: ./gradlew build --no-daemon --stacktrace run: ./gradlew build --no-daemon --stacktrace
- name: Rebuild on Failure - name: Rebuild on Failure
if: ${{ failure() }} if: ${{ failure() }}
run: | run: |
./gradlew clean cleanCache ./gradlew clean cleanCache --refresh-dependencies
./gradlew applyPatches --no-daemon --stacktrace ./gradlew applyAllPatches --no-daemon --stacktrace
./gradlew build --no-daemon --stacktrace ./gradlew build --no-daemon --stacktrace

12
.gitignore vendored
View File

@@ -50,12 +50,12 @@ manifest.mf
*~ *~
# other stuff # other stuff
run/ /run
build-data/ /purpur-server/build.gradle.kts
Purpur-API /purpur-server/src/minecraft
Purpur-MojangAPI /paper-server
Purpur-Server /purpur-api/build.gradle.kts
paper-api-generator /paper-api
*.jar *.jar
test-plugin.settings.gradle.kts test-plugin.settings.gradle.kts

View File

@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Purpur Paperclip Jar" type="JarApplication"> <configuration default="false" name="Run Purpur Paperclip Jar" type="JarApplication">
<option name="JAR_PATH" value="$PROJECT_DIR$/build/libs/purpur-paperclip-1.20.6-R0.1-SNAPSHOT-mojmap.jar" /> <option name="JAR_PATH" value="$PROJECT_DIR$/purpur-server/build/libs/purpur-paperclip-1.21.4-R0.1-SNAPSHOT-mojmap.jar" />
<option name="VM_PARAMETERS" value="-Dcom.mojang.eula.agree" /> <option name="VM_PARAMETERS" value="-Dcom.mojang.eula.agree" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/run" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/run" />
<option name="ALTERNATIVE_JRE_PATH" /> <option name="ALTERNATIVE_JRE_PATH" />

View File

@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Upstream Paper [applyPatches]" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="Upstream Paper [applyAllPatches]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
@@ -10,7 +10,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="applyPatches" /> <option value="applyAllPatches" />
</list> </list>
</option> </option>
<option name="vmOptions" /> <option name="vmOptions" />
@@ -18,7 +18,7 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<ForceTestExec>false</ForceTestExec> <RunAsTest>false</RunAsTest>
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -20,7 +20,7 @@
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest> <RunAsTest>false</RunAsTest>
<method v="2"> <method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Upstream Paper [rebuildPatches]" run_configuration_type="GradleRunConfiguration" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="Upstream Paper [rebuildAllServerPatches]" run_configuration_type="GradleRunConfiguration" />
</method> </method>
</configuration> </configuration>
</component> </component>

View File

@@ -0,0 +1,26 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Upstream Paper [rebuildAllServerPatches]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="rebuildAllServerPatches" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Upstream Paper [rebuildPaperApiPatches]" run_configuration_type="GradleRunConfiguration" />
</method>
</configuration>
</component>

View File

@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Upstream Paper [rebuildPatches]" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="Upstream Paper [rebuildPaperApiPatches]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
@@ -10,7 +10,7 @@
</option> </option>
<option name="taskNames"> <option name="taskNames">
<list> <list>
<option value="rebuildPatches" /> <option value="rebuildPaperApiPatches" />
</list> </list>
</option> </option>
<option name="vmOptions" /> <option name="vmOptions" />
@@ -18,9 +18,9 @@
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled> <DebugAllEnabled>false</DebugAllEnabled>
<ForceTestExec>false</ForceTestExec> <RunAsTest>false</RunAsTest>
<method v="2"> <method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Upstream Paper [applyPatches]" run_configuration_type="GradleRunConfiguration" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="Upstream Paper [applyAllPatches]" run_configuration_type="GradleRunConfiguration" />
</method> </method>
</configuration> </configuration>
</component> </component>

View File

@@ -11,18 +11,12 @@ 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 them yourself. problems for you than make you go back and forth trying to fix them yourself.
Unfortunately, if you use an organization for your PR, it prevents Purpur from Unfortunately, if you use an organization for your PR, it prevents Purpur from
modifying it. This requires us to manually merge your PR, resulting in us modifying it. To avoid this, please do not use repositories on organizations
closing the PR instead of marking it as merged. for PRs.
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 ## Requirements
To get started with PRing changes, you'll need the following software, most of To get started with making changes, you'll need the following software, most of
which can be obtained in (most) package managers such as `apt` (Debian / Ubuntu; 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: you will most likely use this for WSL), `homebrew` (macOS / Linux), and more:
@@ -42,77 +36,94 @@ If you're compiling with Docker, you can use Adoptium's
[`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/) images like so: [`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/) images like so:
```console ```console
# docker run -it -v "$(pwd)":/data --rm eclipse-temurin:21.0.3_9-jdk bash # docker run -it -v "$(pwd)":/data --rm eclipse-temurin:21.0.5_11-jdk bash
Pulling image... Pulling image...
root@abcdefg1234:/# javac -version root@abcdefg1234:/# javac -version
javac 21.0.3 javac 21.0.5
``` ```
## Understanding Patches ## Understanding Patches
Paper is mostly patches and extensions to Spigot. These patches/extensions are Unlike the Purpur API and its implementation, modifications to Paper and Minecraft source files
split into different directories which target certain parts of the code. These are done through patches. These patches/extensions are split into three different sets of two
directories are: categories, which are formatted like so:
- `Purpur-API` - Modifications to `Paper-API`; Under `purpur-api`:
- `Purpur-Server` - Modifications to `Paper-Server`.
Because the entire structure is based on patches and git, a basic understanding - `paper-patches` (applies to the `paper-server/` git repo)
- `sources`: Per-file patches to Paper API classes;
- `features`: Larger feature patches that modify multiple Paper API classes.
Under `purpur-server`:
- `minecraft-patches` (applies to the `purpur-server//` git repo)
- `sources`: Per-file patches to Minecraft classes;
- `resources`: Per-file patches to Minecraft data files;
- `features`: Larger feature patches that modify multiple classes.
- `paper-patches`
- `sources`: Per-file patches to Paper Server classes;
- `features`: Larger feature patches that modify multiple Paper Server classes.
Because this 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: of how to use git is required. A basic tutorial can be found here:
<https://git-scm.com/docs/gittutorial>. <https://git-scm.com/docs/gittutorial>.
Assuming you have already forked the repository: Assuming you have already forked the repository:
1. Clone your fork to your local machine; 1. Clone your fork to your local machine;
2. Type `./gradlew applyPatches` in a terminal to apply the changes from upstream. 2. Type `./gradlew applyAllPatches` in a terminal to apply the patches to both paper and minecraft classes.
On Windows, replace the `./` with `.\` at the beginning for all `gradlew` commands; On Windows, remove `./` from the beginning of `gradlew` commands;
3. cd into `Purpur-Server` for server changes, and `Purpur-API` for API changes. 3. cd into `purpur-server` for server changes, `purpur-api` for API changes,
<!--You can also run `./paper server` or `./paper api` for these same directories `paper-api` for Paper API changes, and `paper-server` for Paper Server changes.
respectively.
1. You can also run `./paper setup`, which allows you to type `paper <command>`
from anywhere in the Paper structure in most cases.-->
`Purpur-Server` and `Purpur-API` aren't git repositories in the traditional sense: `purpur-server/src/minecraft/java` and `purpur-server/src/minecraft/java/resources` are not git repositories in the traditional sense.
Its initial commits are the decompiled and deobfuscated Minecraft source and resource files. The per-file
patches are applied on top of these files as a single, large commit, which is then followed
by the individual feature-patch commits. `paper-api/` and `paper-server/`
follow the same concept; each paper "project" has its own git repository that also includes it's own feature and per-file patches.
- `base` points to the unmodified source before Purpur patches have been applied. ## Understanding the Gradle Tasks
- Each commit after `base` is a patch.
## Adding Patches It can be overwhelming when you look over all the available gradle tasks, but it's pretty straightforward.
Each "project" that includes a local git repository has the following available gradle tasks attached to it:
Adding patches to Purpur is very simple: - `./gradlew apply[project]FeaturePatches` - Applies [project] feature patches
- `./gradlew apply[project]FilePatches` - Applies [project] file patches
- `./gradlew apply[project]Patches` - Applies all [project] patches
- `./gradlew fixup[project]FilePatches` - Puts the currently tracked source changes into the [project] file patches commit
- `./gradlew rebuild[project]FeaturePatches` - Rebuilds [project] feature patches
- `./gradlew rebuild[project]FilePatches` - Rebuilds [project] file patches
- `./gradlew rebuild[project]Patches` - Rebuilds all [project] patches
1. Modify `Purpur-Server` and/or `Purpur-API` with the appropriate changes; Some additional useful tasks are listed below:
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 Purpur. - `./gradlew applyAllPatches` - Applies all patches defined in the paperweight-patcher project and the server project. (equivalent to running `applyPaperPatches` and then `applyAllServerPatches` in a second Gradle invocation)
- `./gradlew applyAllServerFeaturePatches` - Applies all Minecraft and upstream server feature patches (equivalent to `applyMinecraftFeaturePatches applyServerFeaturePatches`)
- `./gradlew applyAllServerFilePatches` - Applies all Minecraft and upstream server file patches (equivalent to `applyMinecraftFilePatches applyServerFilePatches`)
- `./gradlew applyAllServerPatches` - Applies all Minecraft and upstream server patches (equivalent to `applyMinecraftPatches applyServerPatches`)
> ❗ Please note that if you have some specific implementation detail you'd like - `./gradlew rebuildPaperSingleFilePatches` - Fixups and rebuilds all paper single-file patches. This is how you'd make changes to the `build.gradle.kts` files located under `purpur-api` and `purpur-server`
> to document, you should do so in the patch message *or* in comments.
## Modifying Patches ## Modifying (per-file) patches
Modifying previous patches is a bit more complex: This is generally what you need to do when editing files. Updating our
per-file patches is as easy as:
1. Making your changes;
2. Running `./gradlew fixup[project]FilePatches` in the root directory;
3. If nothing went wrong, rebuilding patches with `./gradlew rebuild[project]FilePatches`;
### Method 1 ### Resolving rebase conflicts
If you run into conflicts while running `fixup[project]FilePatches`, you need to go a more
manual route:
This method works by temporarily resetting your `HEAD` to the desired commit to This method works by temporarily resetting your `HEAD` to the desired commit to
edit it using `git rebase`. edit it using `git rebase`.
> ❗ While in the middle of an edit, you will not be able to compile unless you 0. If you have changes you are working on, type `git stash` to store them for
> *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; later;
- You can type `git stash pop` to get them back at any point. - You can type `git stash pop` to get them back at any point.
1. Type `git rebase -i base`; 1. cd into the relevant local git repo and run `git rebase -i base`;
- It should show something like - It should show something like
[this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159) in [this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159) in
the text editor you get. the text editor you get.
@@ -120,31 +131,47 @@ edit it using `git rebase`.
If you don't know how to use `vim` and don't want to 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 learn, enter `:q!` and press enter. Before redoing this step, do
`export EDITOR=nano` for an easier editor to use. `export EDITOR=nano` for an easier editor to use.
1. Replace `pick` with `edit` for the commit/patch you want to modify, and 1. Replace `pick` with `edit` for the commit/patch you want to modify (in this
case the very first commit, `purpur File Patches`), and
"save" the changes; "save" the changes;
- Only do this for **one** commit at a time.
1. Make the changes you want to make to the patch; 1. Make the changes you want to make to the patch;
1. Type `git add .` to add your changes; 1. Run `git add .` to add your changes;
1. Type `git commit --amend` to commit; 1. Run `git commit --amend` to commit;
- **Make sure to add `--amend`** or else a new patch will be created. 1. Run `git rebase --continue` to finish rebasing;
- You can also modify the commit message and author here. 1. Run `./gradlew rebuild[project]FilePatches` in the root directory;
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 ## Adding larger feature patches
If you are simply editing a more recent commit or your change is small, simply Feature patches are exclusively used for large-scale changes that are hard to
making the change at HEAD and then moving the commit after you have tested it track and maintain and that can be optionally dropped, such as the more involved
may be easier. optimizations we have. This makes it easier to update Purpur during Minecraft updates,
since we can temporarily drop these patches and reapply them later.
This method has the benefit of being able to compile to test your change without There is only a very small chance that you will have to use this system, but adding
messing with your HEADs. such patches is very simple:
1. Modify the relevant local git repo with the appropriate changes;
1. Run `git add .` inside that directory to add your changes;
1. Run `git commit` with the desired patch message;
1. Run `./gradlew rebuild[project]FeaturePatches` in the root directory.
Your commit will be converted into a patch that you can then PR into Purpur.
> ❗ 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 larger feature patches
One way of modifying feature patches is to reset to the patch commit and follow
the instructions from the [rebase section](#resolving-rebase-conflicts). If you
are sure there won't be any conflicts from later patches, you can also use the
fixup method.
### Fixup method
#### Manual method #### Manual method
1. Make your change while at HEAD; 1. Make your changes;
1. Make a temporary commit. You don't need to make a message for this; 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 1. Type `git rebase -i base`, move (cut) your temporary commit and
move it under the line of the patch you wish to modify; move it under the line of the patch you wish to modify;
@@ -153,14 +180,14 @@ messing with your HEADs.
message. message.
1. `s`/`squash`: Merge your changes into the patch and use your commit message 1. `s`/`squash`: Merge your changes into the patch and use your commit message
and subject. and subject.
1. Type `./gradlew rebuildPatches` in the root directory; 1. Run `./gradlew rebuild[project]Patches` in the root directory;
- This will modify the appropriate patches based on your commits. - This will modify the appropriate patches based on your commits.
1. PR your modified patch file(s) back to this repository.
#### Automatic method #### Automatic method
1. Make your change while at HEAD; 1. Make your changes;
1. Make a fixup commit. `git commit -a --fixup <hashOfPatchToFix>`; 1. Make a fixup commit: `git commit -a --fixup <hash of patch to fix>`;
- If you want to modify a per-file patch, use `git commit -a --fixup file`
- You can also use `--squash` instead of `--fixup` if you want the commit - You can also use `--squash` instead of `--fixup` if you want the commit
message to also be changed. message to also be changed.
- You can get the hash by looking at `git log` or `git blame`; your IDE can - You can get the hash by looking at `git log` or `git blame`; your IDE can
@@ -170,25 +197,24 @@ messing with your HEADs.
1. Rebase with autosquash: `git rebase -i --autosquash base`. 1. Rebase with autosquash: `git rebase -i --autosquash base`.
This will automatically move your fixup commit to the right place, and you just This will automatically move your fixup commit to the right place, and you just
need to "save" the changes. need to "save" the changes.
1. Type `./gradlew rebuildPatches` in the root directory; 1. Run `./gradlew rebuild[project]Patches` in the root directory. This will modify the
- This will modify the appropriate patches based on your commits. appropriate patches based on your commits.
1. PR your modified patch file(s) back to this repository.
## Rebasing PRs ## Rebasing PRs
Steps to rebase a PR to include the latest changes from `master`. Steps to rebase a PR to include the latest changes from `main`.
These steps assume the `origin` remote is your fork of this repository and `upstream` is the official Purpur repository. These steps assume the `origin` remote is your fork of this repository and `upstream` is the official PurpurMC repository.
1. Pull the latest changes from upstreams master: `git checkout master && git pull upstream master`. 1. Fetch the latest changes from upstream's main: `git fetch upstream`.
1. Checkout feature/fix branch and rebase on master: `git checkout patch-branch && git rebase master`. 1. Checkout your feature/fix branch and rebase on main: `git switch patch-branch && git rebase upstream/main`.
1. Apply updated patches: `./gradlew applyPatches`. 1. Apply updated patches: `./gradlew applyPatches`.
1. If there are conflicts, fix them. 1. If there are conflicts, fix them.
1. If your PR creates new patches instead of modifying existing ones, in both the `Purpur-Server` and `Purpur-API` directories, ensure your newly-created patch is the last commit by either: 1. If your PR creates new feature patches instead of modifying existing ones, 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. * 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. * Running `git rebase --interactive base` and moving the commits to the end.
1. Rebuild patches: `./gradlew rebuildPatches`. 1. Rebuild patches: `./gradlew rebuildPatches`.
1. Commit modified patches. 1. Commit modified patches.
1. Force push changes: `git push --force`. 1. Force push changes: `git push --force`. Make sure you're not deleting any of your commits or changes here!
## PR Policy ## PR Policy
@@ -203,8 +229,9 @@ when making and submitting changes.
## Formatting ## Formatting
All modifications to non-Purpur files should be marked. The one exception to this is All modifications to Minecraft files and Paper files should be marked. For historical reasons,
when modifying javadoc comments, which should not have these markers. API and API-implementation contain a lot of these too, but they are no longer
required.
- You need to add a comment with a short and identifiable description of the patch: - You need to add a comment with a short and identifiable description of the patch:
`// Purpur start - <COMMIT DESCRIPTION>` `// Purpur start - <COMMIT DESCRIPTION>`
@@ -216,16 +243,19 @@ when modifying javadoc comments, which should not have these markers.
with `// Purpur end - <COMMIT DESCRIPTION>`. with `// Purpur end - <COMMIT DESCRIPTION>`.
- One-line changes should have `// Purpur - <COMMIT DESCRIPTION>` at the end of the line. - One-line changes should have `// Purpur - <COMMIT DESCRIPTION>` at the end of the line.
> [!NOTE] These comments are incredibly important to be able to keep track of changes
> across files and to remember what they are for, even a decade into the future.
Here's an example of how to mark changes by Purpur: Here's an example of how to mark changes by Purpur:
```java ```java
entity.getWorld().dontBeStupid(); // Purpur - Was beStupid(), which is bad entity.getWorld().dontBeStupid(); // Purpur - Move away from beStupid()
entity.getFriends().forEach(Entity::explode); entity.getFriends().forEach(Entity::explode);
entity.updateFriends(); entity.updateFriends();
// Purpur start - Use plugin-set spawn // Purpur start - Use plugin-set spawn
// entity.getWorld().explode(entity.getWorld().getSpawn()); // entity.getWorld().explode(entity.getWorld().getSpawn());
Location spawnLocation = ((CraftWorld)entity.getWorld()).getSpawnLocation(); Location spawnLocation = ((CraftWorld) entity.getWorld()).getSpawnLocation();
entity.getWorld().explode(new BlockPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ())); entity.getWorld().explode(new BlockPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ()));
// Purpur end - Use plugin-set spawn // Purpur end - Use plugin-set spawn
``` ```
@@ -236,29 +266,49 @@ into most IDEs and formatters by default. There are a few notes, however:
There are exceptions, especially in Spigot-related files There are exceptions, especially in Spigot-related files
- When in doubt or the code around your change is in a clearly different style, - When in doubt or the code around your change is in a clearly different style,
use the same style as the surrounding code. use the same style as the surrounding code.
- `var` usage is heavily discouraged, as it makes reading patch files a lot harder - Usage of the `var` keyword is discouraged, as it makes reading patch files a
and can lead to confusion during updates due to changed return types. The only lot harder and can lead to confusion during updates due to changed return types.
exception to this is if a line would otherwise be way too long/filled with hard The only exception to this is if a line would otherwise be way too long/filled with
to parse generics in a case where the base type itself is already obvious hard to parse generics in a case where the base type itself is already obvious.
### Imports ### Imports
When adding new imports to a class in a file not created by the current patch, use the fully qualified class name When adding new imports to a Minecraft or Paper class, use the fully qualified class name
instead of adding a new import to the top of the file. If you are using a type a significant number of times, you instead of adding a new import to the top of the file. If you are using a type a significant number of times, you
can add an import with a comment. However, if its only used a couple of times, the FQN is preferred to prevent future can add an import with a comment. However, if it's only used a couple of times, the FQN is preferred to prevent future
patch conflicts in the import section of the file. patch conflicts in the import section of the file.
```java ```java
import org.bukkit.event.Event; import net.minecraft.server.MinecraftServer;
// don't add import here, use FQN like below // don't add import here, use FQN like below
public class SomeEvent extends Event { public class SomeVanillaClass {
public final org.bukkit.Location newLocation; // Purpur - add location public final org.bukkit.Location newLocation; // Purpur - add location
} }
``` ```
### Nullability annotations
We are in the process of switching nullability annotation libraries, so you might need to use one or the other:
**For classes we add**: Fields, method parameters and return types that are nullable should be marked via the
`@Nullable` annotation from `org.jspecify.annotations`. Whenever you create a new class, add `@NullMarked`, meaning types
are assumed to be non-null by default. For less obvious placing such as on generics or arrays, see the [JSpecify docs](https://jspecify.dev/docs/user-guide/).
**For other classes**: Keep using both `@Nullable` and `@NotNull` from `org.jetbrains.annotations`. These
will be replaced later.
## Access Transformers
Sometimes, Vanilla code already contains a field, method, or type you want to access
but the visibility is too low (e.g. a private field in an entity class). Purpur can use access transformers
to change the visibility or remove the final modifier from fields, methods, and classes. Inside the `build-data/purpur.at`
file, you can add ATs that are applied when you `./gradlew applyPatches`. You can read about the format of ATs
[here](https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers).
<!--
## Patch Notes ## Patch Notes
When submitting patches to Purpur, we may ask you to add notes to the patch When submitting feature patches to Purpur, 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 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 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 of some kind. It is very likely that your patch will remain long after we've all
@@ -269,8 +319,8 @@ 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 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. make it easier for us to maintain the patch across major version changes.
If you add a message to your commit in the `Purpur-Server`/`Purpur-API` If you add a message to your commit in the Minecraft source directory,
directories, the rebuild patches script will handle these patch notes the rebuild patches script will handle these patch notes
automatically as part of generating the patch file. If you are not 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 extremely careful, you should always just `squash` or `amend` a patch (see the
above sections on modifying patches) and rebuild. above sections on modifying patches) and rebuild.
@@ -283,7 +333,7 @@ anything but headaches from doing it by hand.
Underneath is an example patch header/note: Underneath is an example patch header/note:
```patch ```patch
From 02abc033533f70ef3165a97bfda3f5c2fa58633a Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com> From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 15 Oct 2017 00:29:07 +0100 Date: Sun, 15 Oct 2017 00:29:07 +0100
Subject: [PATCH] revert serverside behavior of keepalives Subject: [PATCH] revert serverside behavior of keepalives
@@ -306,6 +356,7 @@ index a92bf8967..d0ab87d0f 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java --- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java
``` ```
-->
## Obfuscation Helpers ## Obfuscation Helpers
@@ -380,12 +431,6 @@ object:
return this.level.purpurConfig.useInhabitedTime ? this.inhabitedTime : 0; return this.level.purpurConfig.useInhabitedTime ? this.inhabitedTime : 0;
``` ```
#### Committing changes
All changes to the `PurpurConfig` and `PurpurWorldConfig` 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 ## Testing API changes
### Using the Purpur Test Plugin ### Using the Purpur Test Plugin
@@ -416,36 +461,9 @@ If you use Maven to build your plugin:
## Frequently Asked Questions ## Frequently Asked Questions
### I can't find the NMS file I need!
By default, Purpur (and upstream) only import files we make changes to. If you
would like to make changes to a file that isn't present in `Purpur-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
`./Purpur-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? ### 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. 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 This case most often applies to changes to files like `README.md`, this very
file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth. file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth.
@@ -455,11 +473,11 @@ file (`CONTRIBUTING.md`), the `LICENSE.md` file, and so forth.
This only applies if you're running Windows. If you're running a prior Windows 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. 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 In order to speed up patching process on Windows, it's recommended you get WSL 2.
2. This is available in Windows 10 v2004, build 19041 or higher. (You can check 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 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 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). [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: To set up WSL 2, follow the information here:
<https://docs.microsoft.com/en-us/windows/wsl/install> <https://docs.microsoft.com/en-us/windows/wsl/install>
@@ -473,5 +491,3 @@ everything like usual.
> ❗ Do not use the `/mnt/` directory in WSL! Instead, mount the WSL directories > ❗ Do not use the `/mnt/` directory in WSL! Instead, mount the WSL directories
> in Windows like described here: > in Windows like described here:
> <https://docs.microsoft.com/en-us/windows/wsl/filesystems#view-your-current-directory-in-windows-file-explorer> > <https://docs.microsoft.com/en-us/windows/wsl/filesystems#view-your-current-directory-in-windows-file-explorer>
[MappingViewer]: https://mappings.cephx.dev/

View File

@@ -27,7 +27,7 @@ Join us on Discord:
## Downloads ## Downloads
Downloads can be obtained from the [downloads page](https://purpurmc.org/downloads/) or the [downloads API](https://api.purpurmc.org). Downloads can be obtained from the [downloads page](https://purpurmc.org/downloads/) or the [downloads API](https://api.purpurmc.org).
[![Build Status](https://img.shields.io/github/actions/workflow/status/PurpurMC/Purpur/build.yml?branch=ver%2F1.20.6&event=push&label=Downloads&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9bxSIVh1YQcYhQnSyIiuimVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE0clJ0UVK/F9SaBHjwXE/3t173L0D/PUyU82OMUDVLCOViAuZ7KrQ9YogwujDEGYkZupzopiE5/i6h4+vdzGe5X3uz9Gj5EwG+ATiWaYbFvEG8dSmpXPeJ46woqQQnxOPGnRB4keuyy6/cS447OeZESOdmieOEAuFNpbbmBUNlXiSOKqoGuX7My4rnLc4q+Uqa96TvzCU01aWuU5zEAksYgkiBMioooQyLMRo1UgxkaL9uId/wPGL5JLJVQIjxwIqUCE5fvA/+N2tmZ8Yd5NCcaDzxbY/hoGuXaBRs+3vY9tunACBZ+BKa/krdWD6k/RaS4seAb3bwMV1S5P3gMsdoP9JlwzJkQI0/fk88H5G35QFwrdA95rbW3Mfpw9AmrpK3gAHh8BIgbLXPd4dbO/t3zPN/n4Ax9dyyerighsAAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfmCBMWBjFhOpnxAAACyklEQVQ4y32TXWgdZRCGn8k5Z3e/bzcJRFuoDRqIIPGniaSl1qgXKYhiLUgleFESW1qQ4g94oVKQJmga0ILRBuvfheJFIbY3SmzRFsWgQrTQFlRoKSVXgcMxJiS7++1ukvHiNKGU6FzNDO8MMw8zwn9Yz5c6anKeChxiMk599aq8sZ5Obk3sGNd7G5aZCHJ+Oj8gAwD9I3rSJmyvzLHz+HG5frO+vOaNa3NXiUkKQj9hQ1jQgWrlyCCV6gIdtmBjoJwbPqgL+R08PDQkCUADwD0TerqzxFTJY++vz0l7c0q/F7P5+aNUqyvM2CU2RAV7hsek3XPs3/QHF7/YrSfrDVQrxrErdESNNTYByAp3NmWUTYaGGSuho+QltAGYRdqilChMeKbO4Ijang5+CVJmbcr20PG3n9NiY6ZOvCW9ACMHdDLIeDDIqTWmtAQJV6OMyhOTsqWBQQo/hvP7pFcWeDxwtAQxGqbEq3isI7EOjRy3NyuPPHtOur0UXWMQZXgAX78uP3sJpTBmyHfsGDmotdF+rQWObq/gnSCm9PQ3chnA3qgRgL5jmjXlTM/n7Ny8yJXRY2IA3tur0yaHF8blLoAzj2kaNNBpZvk2iGntuiZBHWLOtXJC3hbzV5SxtDq6yZmzCXOrsRezHNa4YBzlKGN6bQXryD96W+4PU14zGbw/oLMf79EPbAI2g7M9+smP3fqPKVAT81LnFWnzM1y9gYC9gWtwTD6MEsq+Y8Lm7DMZ7cZxt5/T5xd8Fy5SfuC6fA4QZjdd8eEX9eLwAZ1StHKiT1MARStnHtWZH7bpjKIVgKutmipq50O94Mr6+9oKR8ekyy7x5qd9/NmYslynK4WfUjWOqiAFgElZmY+41BTzcrAkW9d9ptO9etgU7I8S3vVyDtkY/JzPwoxXzCJjt6Uy+r/fuGq/3affezkPRSniJ0y2zsqT6+n+BfRHKWgwbKNIAAAAAElFTkSuQmCC)](https://purpurmc.org/downloads/) [![Build Status](https://img.shields.io/github/actions/workflow/status/PurpurMC/Purpur/build.yml?branch=ver%2F1.21.4&event=push&label=Downloads&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9bxSIVh1YQcYhQnSyIiuimVShChVArtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APE0clJ0UVK/F9SaBHjwXE/3t173L0D/PUyU82OMUDVLCOViAuZ7KrQ9YogwujDEGYkZupzopiE5/i6h4+vdzGe5X3uz9Gj5EwG+ATiWaYbFvEG8dSmpXPeJ46woqQQnxOPGnRB4keuyy6/cS447OeZESOdmieOEAuFNpbbmBUNlXiSOKqoGuX7My4rnLc4q+Uqa96TvzCU01aWuU5zEAksYgkiBMioooQyLMRo1UgxkaL9uId/wPGL5JLJVQIjxwIqUCE5fvA/+N2tmZ8Yd5NCcaDzxbY/hoGuXaBRs+3vY9tunACBZ+BKa/krdWD6k/RaS4seAb3bwMV1S5P3gMsdoP9JlwzJkQI0/fk88H5G35QFwrdA95rbW3Mfpw9AmrpK3gAHh8BIgbLXPd4dbO/t3zPN/n4Ax9dyyerighsAAAAGYktHRAAAAAAAAPlDu38AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfmCBMWBjFhOpnxAAACyklEQVQ4y32TXWgdZRCGn8k5Z3e/bzcJRFuoDRqIIPGniaSl1qgXKYhiLUgleFESW1qQ4g94oVKQJmga0ILRBuvfheJFIbY3SmzRFsWgQrTQFlRoKSVXgcMxJiS7++1ukvHiNKGU6FzNDO8MMw8zwn9Yz5c6anKeChxiMk599aq8sZ5Obk3sGNd7G5aZCHJ+Oj8gAwD9I3rSJmyvzLHz+HG5frO+vOaNa3NXiUkKQj9hQ1jQgWrlyCCV6gIdtmBjoJwbPqgL+R08PDQkCUADwD0TerqzxFTJY++vz0l7c0q/F7P5+aNUqyvM2CU2RAV7hsek3XPs3/QHF7/YrSfrDVQrxrErdESNNTYByAp3NmWUTYaGGSuho+QltAGYRdqilChMeKbO4Ijang5+CVJmbcr20PG3n9NiY6ZOvCW9ACMHdDLIeDDIqTWmtAQJV6OMyhOTsqWBQQo/hvP7pFcWeDxwtAQxGqbEq3isI7EOjRy3NyuPPHtOur0UXWMQZXgAX78uP3sJpTBmyHfsGDmotdF+rQWObq/gnSCm9PQ3chnA3qgRgL5jmjXlTM/n7Ny8yJXRY2IA3tur0yaHF8blLoAzj2kaNNBpZvk2iGntuiZBHWLOtXJC3hbzV5SxtDq6yZmzCXOrsRezHNa4YBzlKGN6bQXryD96W+4PU14zGbw/oLMf79EPbAI2g7M9+smP3fqPKVAT81LnFWnzM1y9gYC9gWtwTD6MEsq+Y8Lm7DMZ7cZxt5/T5xd8Fy5SfuC6fA4QZjdd8eEX9eLwAZ1StHKiT1MARStnHtWZH7bpjKIVgKutmipq50O94Mr6+9oKR8ekyy7x5qd9/NmYslynK4WfUjWOqiAFgElZmY+41BTzcrAkW9d9ptO9etgU7I8S3vVyDtkY/JzPwoxXzCJjt6Uy+r/fuGq/3affezkPRSniJ0y2zsqT6+n+BfRHKWgwbKNIAAAAAElFTkSuQmCC)](https://purpurmc.org/downloads/)
Downloads API endpoints: Downloads API endpoints:
* List versions of Minecraft with builds available: * List versions of Minecraft with builds available:
@@ -67,7 +67,7 @@ Maven
<dependency> <dependency>
<groupId>org.purpurmc.purpur</groupId> <groupId>org.purpurmc.purpur</groupId>
<artifactId>purpur-api</artifactId> <artifactId>purpur-api</artifactId>
<version>1.20.6-R0.1-SNAPSHOT</version> <version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
``` ```
@@ -80,7 +80,7 @@ repositories {
``` ```
```kotlin ```kotlin
dependencies { dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.20.5-R0.1-SNAPSHOT") compileOnly("org.purpurmc.purpur:purpur-api:1.21.4-R0.1-SNAPSHOT")
} }
``` ```

View File

@@ -8,3 +8,7 @@
# To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId: # To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId:
# minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter # minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter
# minecraft net/minecraft/world/level/entity/LevelEntityGetter.java # minecraft net/minecraft/world/level/entity/LevelEntityGetter.java
# To import minecraft data files, like the default chat type, use `mc_data` as the prefix:
# mc_data chat_type/chat.json
# mc_data dimension_type/overworld.json
#

10
build-data/purpur.at Normal file
View File

@@ -0,0 +1,10 @@
# This file is auto generated, any changes may be overridden!
# See CONTRIBUTING.md on how to add access transformers.
protected net.minecraft.world.entity.Entity dimensions
public net.minecraft.world.entity.Entity updateInWaterStateAndDoWaterCurrentPushing()V
public net.minecraft.world.entity.LivingEntity canGlide()Z
public net.minecraft.world.entity.monster.Shulker MAX_SCALE
public net.minecraft.world.entity.player.Player canGlide()Z
public net.minecraft.world.level.block.entity.FuelValues values
public-f net.minecraft.world.entity.EntityType dimensions
public-f net.minecraft.world.level.block.state.BlockBehaviour explosionResistance

View File

@@ -2,28 +2,49 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins { plugins {
java java // TODO java launcher tasks
`maven-publish` id("io.papermc.paperweight.patcher") version "2.0.0-beta.14"
id("io.papermc.paperweight.patcher") version "1.6.3"
}
allprojects {
apply(plugin = "java")
apply(plugin = "maven-publish")
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
} }
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
paperweight {
upstreams.paper {
ref = providers.gradleProperty("paperCommit")
patchFile {
path = "paper-server/build.gradle.kts"
outputFile = file("purpur-server/build.gradle.kts")
patchFile = file("purpur-server/build.gradle.kts.patch")
}
patchFile {
path = "paper-api/build.gradle.kts"
outputFile = file("purpur-api/build.gradle.kts")
patchFile = file("purpur-api/build.gradle.kts.patch")
}
patchDir("paperApi") {
upstreamPath = "paper-api"
excludes = setOf("build.gradle.kts")
patchesDir = file("purpur-api/paper-patches")
outputDir = file("paper-api")
}
}
}
subprojects { subprojects {
tasks.withType<JavaCompile>().configureEach { apply(plugin = "java-library")
apply(plugin = "maven-publish")
extensions.configure<JavaPluginExtension> {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
tasks.withType<JavaCompile> {
options.encoding = Charsets.UTF_8.name() options.encoding = Charsets.UTF_8.name()
options.release = 21 options.release = 21
options.isFork = true
} }
tasks.withType<Javadoc> { tasks.withType<Javadoc> {
options.encoding = Charsets.UTF_8.name() options.encoding = Charsets.UTF_8.name()
@@ -38,67 +59,18 @@ subprojects {
events(TestLogEvent.STANDARD_OUT) events(TestLogEvent.STANDARD_OUT)
} }
} }
tasks.withType<AbstractArchiveTask>().configureEach {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
repositories { repositories {
mavenCentral() mavenCentral()
maven(paperMavenPublicUrl) maven(paperMavenPublicUrl)
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // TODO - Adventure snapshot
maven("https://jitpack.io") maven("https://jitpack.io")
} }
}
repositories { extensions.configure<PublishingExtension> {
mavenCentral()
maven(paperMavenPublicUrl) {
content {
onlyForConfigurations(configurations.paperclip.name)
}
}
}
dependencies {
remapper("net.fabricmc:tiny-remapper:0.10.1:fat")
decompiler("org.vineflower:vineflower:1.10.1")
paperclip("io.papermc:paperclip:3.0.3")
}
paperweight {
serverProject = project(":purpur-server")
remapRepo = paperMavenPublicUrl
decompileRepo = paperMavenPublicUrl
usePaperUpstream(providers.gradleProperty("paperCommit")) {
withPaperPatcher {
apiPatchDir = layout.projectDirectory.dir("patches/api")
apiOutputDir = layout.projectDirectory.dir("Purpur-API")
serverPatchDir = layout.projectDirectory.dir("patches/server")
serverOutputDir = layout.projectDirectory.dir("Purpur-Server")
}
patchTasks.register("generatedApi") {
isBareDirectory = true
upstreamDirPath = "paper-api-generator/generated"
patchDir = layout.projectDirectory.dir("patches/generated-api")
outputDir = layout.projectDirectory.dir("paper-api-generator/generated")
}
}
}
tasks.generateDevelopmentBundle {
apiCoordinates = "org.purpurmc.purpur:purpur-api"
mojangApiCoordinates = "io.papermc.paper:paper-mojangapi"
libraryRepositories = listOf(
"https://repo.maven.apache.org/maven2/",
paperMavenPublicUrl,
"https://repo.purpurmc.org/snapshots",
"https://s01.oss.sonatype.org/content/repositories/snapshots/", // TODO - Adventure snapshot
)
}
allprojects {
publishing {
repositories { repositories {
maven("https://repo.purpurmc.org/snapshots") { maven("https://repo.purpurmc.org/snapshots") {
name = "purpur" name = "purpur"
@@ -108,14 +80,6 @@ allprojects {
} }
} }
publishing {
publications.create<MavenPublication>("devBundle") {
artifact(tasks.generateDevelopmentBundle) {
artifactId = "dev-bundle"
}
}
}
tasks.register("printMinecraftVersion") { tasks.register("printMinecraftVersion") {
doLast { doLast {
println(providers.gradleProperty("mcVersion").get().trim()) println(providers.gradleProperty("mcVersion").get().trim())

View File

@@ -1,10 +1,10 @@
group = org.purpurmc.purpur group = org.purpurmc.purpur
version = 1.20.6-R0.1-SNAPSHOT version = 1.21.4-R0.1-SNAPSHOT
mcVersion = 1.20.6 mcVersion = 1.21.4
paperCommit = eee55d019fe80372c2e08ccd1d0a94c066cda926 paperCommit = 54b2e9d9738ce32e2f415c321f20e3fc07063c14
org.gradle.configuration-cache = true
org.gradle.caching = true org.gradle.caching = true
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.vfs.watch = false org.gradle.vfs.watch = false
org.gradle.jvmargs = -Xmx3G

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

14
gradlew vendored
View File

@@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
@@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # 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"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command;
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# and any embedded shellness will be escaped. # shell script including quotes and variable substitutions, so put them in
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # double quotes to make sure that they get re-expanded; and
# treated as '${Hostname}' itself on the command line. # * put everything else in single quotes, so that it's not re-expanded.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \

20
gradlew.bat vendored
View File

@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
goto fail goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
goto fail goto fail

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] LivingEntity#broadcastItemBreak
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index b777e530122549455dcce6fac8d4a151c1c0af42..aba9952b2256b058eb413ce93f3305c861a200db 100644 index 5c29956c6db53440322330ff723c7087193641f1..e1079c5c4be99e75a646c090189678dd131f210e 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java --- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -1447,4 +1447,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource @@ -1447,4 +1447,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] LivingEntity#broadcastItemBreak
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index aa351df679f300018367244c7ccb3e5a59e9276f..11bd76d79bbfff68734d8ee1095f21c5c50e7bde 100644 index a1e715629313346f670bce92483996122b0f1d7b..386647f6000c71c59ab8d7875219eefdc5a3d7ef 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1173,4 +1173,12 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { @@ -1181,4 +1181,12 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
this.getHandle().setYBodyRot(bodyYaw); this.getHandle().setYBodyRot(bodyYaw);
} }
// Paper end - body yaw API // Paper end - body yaw API

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Add mending multiplier
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
index ce608784e0e35b67dde377436aaf42c956ce0644..f5debc8ddc496cd3e2d8b253511ee5cc9a723b38 100644 index 7130d483ccdce26526e715bd7e68d2e896e6215f..40d168d225932717b8ac8bdd27dfe2a202bc2808 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -366,13 +366,15 @@ public class ExperienceOrb extends Entity { @@ -372,13 +372,15 @@ public class ExperienceOrb extends Entity {
} }
} }
@@ -27,7 +27,7 @@ index ce608784e0e35b67dde377436aaf42c956ce0644..f5debc8ddc496cd3e2d8b253511ee5cc
public int getValue() { public int getValue() {
return this.value; return this.value;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 8c7508fc6163a73740aedbe9c4dee2d21c4fa0fa..03819b5d991d91c2e7f5e2eae50e1a7e4197336b 100644 index 02b8333222668c3419296ec5513c1c4e8e8d1a79..3c614b8f62c0d3839ebc4e948c952d52c4f66819 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -119,6 +119,7 @@ public class PurpurWorldConfig { @@ -119,6 +119,7 @@ public class PurpurWorldConfig {

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Shears can have looting enchantment
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
index a024c697a65bbab27408da1d6a75e531d9719b47..e4fab82b369f2c2ea0d8c8acd814d06140d551fc 100644 index 44b79a7c2f8b95a484d1999fa2167ce588f7985b..68632372c8704058f35f12e0ae6cdd98ebd55937 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java --- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
@@ -105,7 +105,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -104,7 +104,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
if (ishearable.readyForShearing()) { if (ishearable.readyForShearing()) {
// CraftBukkit start // CraftBukkit start
// Paper start - Add drops to shear events // Paper start - Add drops to shear events
@@ -31,7 +31,7 @@ index 2ee48ac3b665db2b02bcb1a30ec972d43a3725b0..59e8f5431ce5026209e1428b5fa5b548
} }
// Paper end - custom shear drops // Paper end - custom shear drops
diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
index 06fac8dae42451f912c2db14d792461cee3dba83..a7c95199234231db14faa4a07953bcde57d9861d 100644 index 06fac8dae42451f912c2db14d792461cee3dba83..e5a84dd5f1a375dd44b9d14dc7f44339bd8ddf3a 100644
--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java --- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
@@ -161,7 +161,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo @@ -161,7 +161,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
@@ -39,7 +39,7 @@ index 06fac8dae42451f912c2db14d792461cee3dba83..a7c95199234231db14faa4a07953bcde
// CraftBukkit start // CraftBukkit start
// Paper start - custom shear drops // Paper start - custom shear drops
- java.util.List<ItemStack> drops = this.generateDefaultDrops(); - java.util.List<ItemStack> drops = this.generateDefaultDrops();
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur + java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur
org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
if (event != null) { if (event != null) {
if (event.isCancelled()) { if (event.isCancelled()) {
@@ -61,19 +61,19 @@ index 06fac8dae42451f912c2db14d792461cee3dba83..a7c95199234231db14faa4a07953bcde
} }
return dropEntities; return dropEntities;
diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
index 9e617b3f1ec4eac5f83bdf19a3563cdc81b008d8..6b1244d3957e7f62c96ffd34692b8916337839fd 100644 index ca63c98bc45584812c0fb2af84a63aa08daa9a9e..17b49186293578c06144a476473324a9a1f6fcbb 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java --- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java +++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
@@ -297,7 +297,7 @@ public class Sheep extends Animal implements Shearable { @@ -296,7 +296,7 @@ public class Sheep extends Animal implements Shearable {
if (!this.level().isClientSide && this.readyForShearing()) { if (!this.level().isClientSide && this.readyForShearing()) {
// CraftBukkit start // CraftBukkit start
// Paper start - custom shear drops // Paper start - custom shear drops
- java.util.List<ItemStack> drops = this.generateDefaultDrops(); - java.util.List<ItemStack> drops = this.generateDefaultDrops();
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur + java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur
org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
if (event != null) { if (event != null) {
if (event.isCancelled()) { if (event.isCancelled()) {
@@ -322,12 +322,13 @@ public class Sheep extends Animal implements Shearable { @@ -321,12 +321,13 @@ public class Sheep extends Animal implements Shearable {
@Override @Override
public void shear(SoundSource shearedSoundCategory) { public void shear(SoundSource shearedSoundCategory) {
// Paper start - custom shear drops // Paper start - custom shear drops
@@ -90,19 +90,19 @@ index 9e617b3f1ec4eac5f83bdf19a3563cdc81b008d8..6b1244d3957e7f62c96ffd34692b8916
for (int j = 0; j < count; ++j) { for (int j = 0; j < count; ++j) {
dropEntities.add(new ItemStack(Sheep.ITEM_BY_DYE.get(this.getColor()))); dropEntities.add(new ItemStack(Sheep.ITEM_BY_DYE.get(this.getColor())));
diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
index 69cdccca01fe7d10e6d958e16d91efe08f699505..3b74931ae4e3a869d8db38c119e57b44af887859 100644 index b3bb0d55da0278d4981830f7073bb326bc836215..7bd2d2b9bb1275fa8e4bdc6d498a59e47838930f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java --- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
@@ -189,7 +189,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM @@ -190,7 +190,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
// CraftBukkit start // CraftBukkit start
// Paper start - custom shear drops // Paper start - custom shear drops
- java.util.List<ItemStack> drops = this.generateDefaultDrops(); - java.util.List<ItemStack> drops = this.generateDefaultDrops();
+ java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur + java.util.List<ItemStack> drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur
org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
if (event != null) { if (event != null) {
if (event.isCancelled()) { if (event.isCancelled()) {
@@ -222,11 +222,20 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM @@ -223,11 +223,20 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
@Override @Override
public void shear(SoundSource shearedSoundCategory) { public void shear(SoundSource shearedSoundCategory) {
// Paper start - custom shear drops // Paper start - custom shear drops
@@ -126,35 +126,90 @@ index 69cdccca01fe7d10e6d958e16d91efe08f699505..3b74931ae4e3a869d8db38c119e57b44
} }
diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
index e9f9b041ae7195e9d23bd446454b1d8c47a1ace1..03b1023e182744a84d324bdad082cc1b9e574e30 100644 index 71efea7a6bfb5662890dae5faae27a3c80afad2b..f3aae2c50d05a05ad4aef36d432b87b431ba07e8 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java --- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java +++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java
@@ -159,7 +159,7 @@ public class Bogged extends AbstractSkeleton implements Shearable { @@ -104,7 +104,7 @@ public class Bogged extends AbstractSkeleton implements Shearable {
if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
// CraftBukkit start
// Paper start - expose drops in event
- java.util.List<net.minecraft.world.item.ItemStack> drops = generateDefaultDrops();
+ java.util.List<net.minecraft.world.item.ItemStack> drops = generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur
final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
if (event != null) {
if (event.isCancelled()) {
@@ -171,7 +171,7 @@ public class Bogged extends AbstractSkeleton implements Shearable {
@Override
public void shear(SoundSource shearedSoundCategory) {
// Paper start - shear drop API
- this.shear(shearedSoundCategory, generateDefaultDrops());
+ this.shear(shearedSoundCategory, generateDefaultDrops(0)); // Purpur
}
@Override
@@ -184,7 +184,7 @@ public class Bogged extends AbstractSkeleton implements Shearable {
private void spawnShearedMushrooms() {
// Paper start - shear drops API
- this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise.
+ this.spawnDrops(generateDefaultDrops(0)); // Only here for people calling spawnSheardMushrooms. Not used otherwise. // Purpur
}
private void spawnDrops(java.util.List<net.minecraft.world.item.ItemStack> drops) {
drops.forEach(stack -> {
@@ -193,14 +193,22 @@ public class Bogged extends AbstractSkeleton implements Shearable {
this.forceDrops = false;
});
}
- private void generateShearedMushrooms(java.util.function.Consumer<ItemStack> stackConsumer) {
+ private void generateShearedMushrooms(java.util.function.Consumer<ItemStack> stackConsumer, int looting) { // Purpur
// Paper end - shear drops API
Level world = this.level();
if (world instanceof ServerLevel worldserver) {
LootTable loottable = worldserver.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR);
LootParams lootparams = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.SHEARING);
- ObjectListIterator objectlistiterator = loottable.getRandomItems(lootparams).iterator();
+ // Purpur start
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<ItemStack> randomItemsList = loottable.getRandomItems(lootparams);
+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting && looting > 0) {
+ for (int i = 0; i < looting; i++) {
+ randomItemsList.addAll(loottable.getRandomItems(lootparams));
+ }
+ }
+ ObjectListIterator objectlistiterator = randomItemsList.iterator();
+ // Purpur end
while (objectlistiterator.hasNext()) {
ItemStack itemstack = (ItemStack) objectlistiterator.next();
@@ -213,9 +221,9 @@ public class Bogged extends AbstractSkeleton implements Shearable {
// Paper start - shear drops API // Paper start - shear drops API
@Override @Override
- public java.util.List<ItemStack> generateDefaultDrops() { - public java.util.List<ItemStack> generateDefaultDrops() {
+ public java.util.List<ItemStack> generateDefaultDrops(int looting) { // Purpur + public java.util.List<ItemStack> generateDefaultDrops(int looting) { // Purpur
final java.util.List<ItemStack> drops = new java.util.ArrayList<>(); final java.util.List<ItemStack> drops = new java.util.ArrayList<>();
this.generateShearedMushrooms(drops::add); - this.generateShearedMushrooms(drops::add);
+ this.generateShearedMushrooms(drops::add, looting); // Purpur
return drops; return drops;
}
// Paper end - shear drops API
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index cd27c2a3343133d688592791bec2a031410ff93f..91d5c175752f6ee850adada6802c8af8f833d9c7 100644 index 7ad309e81ec61a6f2553e9ffeb9a986f4d569b37..3d5c89238ee3fbd3c9b33107995ae47733539960 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java --- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -391,6 +391,7 @@ public class PurpurConfig { @@ -393,6 +393,7 @@ public class PurpurConfig {
}
public static boolean allowInfinityMending = false; }
public static boolean allowCrossbowInfinity = true;
+ public static boolean allowShearsLooting = false; + public static boolean allowShearsLooting = false;
public static boolean allowUnsafeEnchants = false; public static boolean allowInapplicableEnchants = false;
public static boolean allowInapplicableEnchants = true; public static boolean allowIncompatibleEnchants = false;
public static boolean allowIncompatibleEnchants = true; public static boolean allowHigherEnchantsLevels = false;
@@ -413,6 +414,7 @@ public class PurpurConfig { @@ -416,6 +417,7 @@ public class PurpurConfig {
}
set("settings.enchantment.anvil.allow-unsafe-enchants", null);
} }
allowInfinityMending = getBoolean("settings.enchantment.allow-infinity-and-mending-together", allowInfinityMending);
allowCrossbowInfinity = getBoolean("settings.enchantment.allow-infinity-on-crossbow", allowCrossbowInfinity);
+ allowShearsLooting = getBoolean("settings.enchantment.allow-looting-on-shears", allowShearsLooting); + allowShearsLooting = getBoolean("settings.enchantment.allow-looting-on-shears", allowShearsLooting);
allowUnsafeEnchants = getBoolean("settings.enchantment.anvil.allow-unsafe-enchants", allowUnsafeEnchants);
allowInapplicableEnchants = getBoolean("settings.enchantment.anvil.allow-inapplicable-enchants", allowInapplicableEnchants); allowInapplicableEnchants = getBoolean("settings.enchantment.anvil.allow-inapplicable-enchants", allowInapplicableEnchants);
allowIncompatibleEnchants = getBoolean("settings.enchantment.anvil.allow-incompatible-enchants", allowIncompatibleEnchants); allowIncompatibleEnchants = getBoolean("settings.enchantment.anvil.allow-incompatible-enchants", allowIncompatibleEnchants);
allowHigherEnchantsLevels = getBoolean("settings.enchantment.anvil.allow-higher-enchants-levels", allowHigherEnchantsLevels);

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Sat, 12 Jun 2021 12:35:38 -0400
Subject: [PATCH] Build System Changes
diff --git a/build.gradle.kts b/build.gradle.kts
index 65e67b8726f1e19a6bcb1fe2f448e4ab68df11d1..892e78b1d2d29dc54def03fcb6d85a93ad56d84c 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -121,6 +121,8 @@ tasks.jar {
}
tasks.withType<Javadoc> {
+ (options as StandardJavadocDocletOptions).addStringOption("-add-modules", "jdk.incubator.vector") // Purpur - our javadocs need this for pufferfish's SIMD patch
+ (options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet") // Purpur - silence Paper's bajillion javadoc warnings
val options = options as StandardJavadocDocletOptions
options.overview = "src/main/javadoc/overview.html"
options.use()

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fredthedoggy <45927799+fredthedoggy@users.noreply.github.com>
Date: Thu, 19 Aug 2021 20:04:18 -0400
Subject: [PATCH] Purpur client support
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 6c327a07bf8a6aa11a2d7dad12b2830acc539484..d972cb242102a3ee7c017299aed64340628c79d8 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3806,4 +3806,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@Override
Spigot spigot();
// Spigot end
+
+ // Purpur start
+ /**
+ * Allows you to get if player uses Purpur Client
+ *
+ * @return True if Player uses Purpur Client
+ */
+ public boolean usesPurpurClient();
+ // Purpur end
}

View File

@@ -1,124 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 5 Jun 2020 23:32:38 -0500
Subject: [PATCH] Default permissions
diff --git a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
index 7763d6101ac61900db1e2310966b99584539fd0e..d5a42707d365ffd72532bbb1a59a1ca7145f9918 100644
--- a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
+++ b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
@@ -18,6 +18,7 @@ public final class CommandPermissions {
DefaultPermissions.registerPermission(PREFIX + "plugins", "Allows the user to view the list of plugins running on this server", PermissionDefault.TRUE, commands);
DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload the server settings", PermissionDefault.OP, commands);
DefaultPermissions.registerPermission(PREFIX + "version", "Allows the user to view the version of the server", PermissionDefault.TRUE, commands);
+ DefaultPermissions.registerPermission(PREFIX + "purpur", "Allows the user to use the purpur command", PermissionDefault.OP, commands); // Purpur
commands.recalculatePermissibles();
return commands;
diff --git a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
index e1a4ddf2c07cdd242fa8054a0152522fe4039e85..8e481e3815f5645ee92f0d229e5ff25c8fc9a6c2 100644
--- a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
+++ b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
@@ -89,6 +89,8 @@ public final class DefaultPermissions {
CommandPermissions.registerPermissions(parent);
BroadcastPermissions.registerPermissions(parent);
+ PurpurPermissions.registerPermissions(); // Purpur
+
parent.recalculatePermissibles();
}
}
diff --git a/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java b/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java
new file mode 100644
index 0000000000000000000000000000000000000000..baec4c87d7ea4d54934ca22fd1eb7b46dd69061b
--- /dev/null
+++ b/src/main/java/org/bukkit/util/permissions/PurpurPermissions.java
@@ -0,0 +1,87 @@
+package org.bukkit.util.permissions;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Mob;
+import org.bukkit.permissions.Permission;
+import org.bukkit.permissions.PermissionDefault;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public final class PurpurPermissions {
+ private static final String ROOT = "purpur";
+ private static final String PREFIX = ROOT + ".";
+ private static final Set<String> mobs = new HashSet<>();
+
+ static {
+ for (EntityType mob : EntityType.values()) {
+ Class<? extends Entity> clazz = mob.getEntityClass();
+ if (clazz != null && Mob.class.isAssignableFrom(clazz)) {
+ mobs.add(mob.getName());
+ }
+ }
+ }
+
+ @NotNull
+ public static Permission registerPermissions() {
+ Permission purpur = DefaultPermissions.registerPermission(ROOT, "Gives the user the ability to use all Purpur utilities and commands", PermissionDefault.FALSE);
+
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.six", "Gives the user six rows of enderchest space", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.five", "Gives the user five rows of enderchest space", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.four", "Gives the user four rows of enderchest space", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.three", "Gives the user three rows of enderchest space", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.two", "Gives the user two rows of enderchest space", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "enderchest.rows.one", "Gives the user one row of enderchest space", PermissionDefault.FALSE, purpur);
+
+ DefaultPermissions.registerPermission(PREFIX + "debug.f3n", "Allows the user to use F3+N keybind to swap gamemodes", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "joinfullserver", "Allows the user to join a full server", PermissionDefault.OP, purpur);
+
+ DefaultPermissions.registerPermission(PREFIX + "drop.spawners", "Allows the user to drop spawner cage when broken with diamond pickaxe with silk touch", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "place.spawners", "Allows the user to place spawner cage in the world", PermissionDefault.FALSE, purpur);
+
+ DefaultPermissions.registerPermission(PREFIX + "mending_shift_click", "Allows the user to use shift-right-click to mend items", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "inventory_totem", "Uses a totem from anywhere in the user's inventory on death", PermissionDefault.FALSE, purpur);
+
+ Permission anvil = DefaultPermissions.registerPermission(PREFIX + "anvil", "Allows the user to use all anvil color and format abilities", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "anvil.color", "Allows the user to use color codes in an anvil", PermissionDefault.FALSE, anvil);
+ DefaultPermissions.registerPermission(PREFIX + "anvil.minimessage", "Allows the user to use minimessage tags in an anvil", PermissionDefault.FALSE, anvil);
+ DefaultPermissions.registerPermission(PREFIX + "anvil.remove_italics", "Allows the user to remove italics in an anvil", PermissionDefault.FALSE, anvil);
+ DefaultPermissions.registerPermission(PREFIX + "anvil.format", "Allows the user to use format codes in an anvil", PermissionDefault.FALSE, anvil);
+ anvil.recalculatePermissibles();
+
+ Permission book = DefaultPermissions.registerPermission(PREFIX + "book", "Allows the user to use color codes on books", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "book.color.edit", "Allows the user to use color codes on books when editing", PermissionDefault.FALSE, book);
+ DefaultPermissions.registerPermission(PREFIX + "book.color.sign", "Allows the user to use color codes on books when signing", PermissionDefault.FALSE, book);
+ book.recalculatePermissibles();
+
+ Permission sign = DefaultPermissions.registerPermission(PREFIX + "sign", "Allows the user to use all sign abilities", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission(PREFIX + "sign.edit", "Allows the user to click signs to open sign editor", PermissionDefault.FALSE, sign);
+ DefaultPermissions.registerPermission(PREFIX + "sign.color", "Allows the user to use color codes on signs", PermissionDefault.FALSE, sign);
+ DefaultPermissions.registerPermission(PREFIX + "sign.style", "Allows the user to use style codes on signs", PermissionDefault.FALSE, sign);
+ DefaultPermissions.registerPermission(PREFIX + "sign.magic", "Allows the user to use magic/obfuscate code on signs", PermissionDefault.FALSE, sign);
+ sign.recalculatePermissibles();
+
+ Permission ride = DefaultPermissions.registerPermission("allow.ride", "Allows the user to ride all mobs", PermissionDefault.FALSE, purpur);
+ for (String mob : mobs) {
+ DefaultPermissions.registerPermission("allow.ride." + mob, "Allows the user to ride " + mob, PermissionDefault.FALSE, ride);
+ }
+ ride.recalculatePermissibles();
+
+ Permission special = DefaultPermissions.registerPermission("allow.special", "Allows the user to use all mobs special abilities", PermissionDefault.FALSE, purpur);
+ for (String mob : mobs) {
+ DefaultPermissions.registerPermission("allow.special." + mob, "Allows the user to use " + mob + " special ability", PermissionDefault.FALSE, special);
+ }
+ special.recalculatePermissibles();
+
+ Permission powered = DefaultPermissions.registerPermission("allow.powered", "Allows the user to toggle all mobs powered state", PermissionDefault.FALSE, purpur);
+ DefaultPermissions.registerPermission("allow.powered.creeper", "Allows the user to toggle creeper powered state", PermissionDefault.FALSE, powered);
+ powered.recalculatePermissibles();
+
+ DefaultPermissions.registerPermission(PREFIX + "portal.instant", "Allows the user to bypass portal wait time", PermissionDefault.FALSE, purpur);
+
+ purpur.recalculatePermissibles();
+ return purpur;
+ }
+}

View File

@@ -1,198 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 4 May 2019 00:57:16 -0500
Subject: [PATCH] Ridables
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 62e3793903905b94eb1a120345015149abb33713..50344412a04f3008439e337ecf9dd09c7f853bc9 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -1155,4 +1155,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
@NotNull String getScoreboardEntryName();
// Paper end - entity scoreboard name
+
+ // Purpur start
+ /**
+ * Get the riding player
+ *
+ * @return Riding player
+ */
+ @Nullable
+ Player getRider();
+
+ /**
+ * Check if entity is being ridden
+ *
+ * @return True if being ridden
+ */
+ boolean hasRider();
+
+ /**
+ * Check if entity is ridable
+ *
+ * @return True if ridable
+ */
+ boolean isRidable();
+
+ /**
+ * Check if entity is ridable in water
+ *
+ * @return True if ridable in water
+ */
+ boolean isRidableInWater();
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/RidableMoveEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/RidableMoveEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a037df01b07af9ffb98b67aca412c1d34fade03b
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/RidableMoveEvent.java
@@ -0,0 +1,103 @@
+package org.purpurmc.purpur.event.entity;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.Location;
+import org.bukkit.entity.Mob;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Triggered when a ridable mob moves with a rider
+ */
+public class RidableMoveEvent extends EntityEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean canceled;
+ private final Player rider;
+ private Location from;
+ private Location to;
+
+ public RidableMoveEvent(@NotNull Mob entity, @NotNull Player rider, @NotNull Location from, @NotNull Location to) {
+ super(entity);
+ this.rider = rider;
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ @NotNull
+ public Mob getEntity() {
+ return (Mob) entity;
+ }
+
+ @NotNull
+ public Player getRider() {
+ return rider;
+ }
+
+ public boolean isCancelled() {
+ return canceled;
+ }
+
+ public void setCancelled(boolean cancel) {
+ canceled = cancel;
+ }
+
+ /**
+ * Gets the location this entity moved from
+ *
+ * @return Location the entity moved from
+ */
+ @NotNull
+ public Location getFrom() {
+ return from;
+ }
+
+ /**
+ * Sets the location to mark as where the entity moved from
+ *
+ * @param from New location to mark as the entity's previous location
+ */
+ public void setFrom(@NotNull Location from) {
+ validateLocation(from);
+ this.from = from;
+ }
+
+ /**
+ * Gets the location this entity moved to
+ *
+ * @return Location the entity moved to
+ */
+ @NotNull
+ public Location getTo() {
+ return to;
+ }
+
+ /**
+ * Sets the location that this entity will move to
+ *
+ * @param to New Location this entity will move to
+ */
+ public void setTo(@NotNull Location to) {
+ validateLocation(to);
+ this.to = to;
+ }
+
+ private void validateLocation(@NotNull Location loc) {
+ Preconditions.checkArgument(loc != null, "Cannot use null location!");
+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!");
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/RidableSpacebarEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/RidableSpacebarEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d3a7d898e3278ce998d713dafbb4b354dad7fc7
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/RidableSpacebarEvent.java
@@ -0,0 +1,37 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+public class RidableSpacebarEvent extends EntityEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled;
+
+ public RidableSpacebarEvent(@NotNull Entity entity) {
+ super(entity);
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ cancelled = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Tue, 23 Jul 2019 06:50:55 -0500
Subject: [PATCH] Allow inventory resizing
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java
index 59b375569a75cb1e1f7c610f96078e102ec0d3ed..a3f74891abbdc51dbbddaeb511f2754e0603c904 100644
--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java
+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java
@@ -166,7 +166,7 @@ public enum InventoryType {
SMITHING_NEW(4, "Upgrade Gear"),
;
- private final int size;
+ private int size; public void setDefaultSize(int size) { this.size = size; } // Purpur - remove final and add setter
private final String title;
private final boolean isCreatable;

View File

@@ -1,138 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 18 Oct 2019 22:50:05 -0500
Subject: [PATCH] Llama API
diff --git a/src/main/java/org/bukkit/entity/Llama.java b/src/main/java/org/bukkit/entity/Llama.java
index bc84b892cae5fe7019a3ad481e9da79956efa1fe..48eb5b00c460cccde29d327cef1d63fc04d6a829 100644
--- a/src/main/java/org/bukkit/entity/Llama.java
+++ b/src/main/java/org/bukkit/entity/Llama.java
@@ -119,4 +119,20 @@ public interface Llama extends ChestedHorse, RangedEntity { // Paper
@org.jetbrains.annotations.Nullable
Llama getCaravanTail();
// Paper end
+
+ // Purpur start
+ /**
+ * Check if this Llama should attempt to join a caravan
+ *
+ * @return True if Llama is allowed to join a caravan
+ */
+ boolean shouldJoinCaravan();
+
+ /**
+ * Set if this Llama should attempt to join a caravan
+ *
+ * @param shouldJoinCaravan True to allow joining a caravan
+ */
+ void setShouldJoinCaravan(boolean shouldJoinCaravan);
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/LlamaJoinCaravanEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/LlamaJoinCaravanEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8849bb0becb16db907fa648cca2e98ab9d957c75
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/LlamaJoinCaravanEvent.java
@@ -0,0 +1,61 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.entity.Llama;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a Llama tries to join a caravan.
+ * <p>
+ * Cancelling the event will not let the Llama join. To prevent future attempts
+ * at joining a caravan use {@link Llama#setShouldJoinCaravan(boolean)}.
+ */
+public class LlamaJoinCaravanEvent extends EntityEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean canceled;
+ private final Llama head;
+
+ public LlamaJoinCaravanEvent(@NotNull Llama llama, @NotNull Llama head) {
+ super(llama);
+ this.head = head;
+ }
+
+ @Override
+ @NotNull
+ public Llama getEntity() {
+ return (Llama) entity;
+ }
+
+ /**
+ * Get the Llama that this Llama is about to follow
+ *
+ * @return Llama about to be followed
+ */
+ @NotNull
+ public Llama getHead() {
+ return head;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return canceled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ canceled = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/LlamaLeaveCaravanEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/LlamaLeaveCaravanEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c268c35b541a222d50875c29770c846a8ffcc4f8
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/LlamaLeaveCaravanEvent.java
@@ -0,0 +1,34 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.entity.Llama;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a Llama leaves a caravan
+ */
+public class LlamaLeaveCaravanEvent extends EntityEvent {
+ private static final HandlerList handlers = new HandlerList();
+
+ public LlamaLeaveCaravanEvent(@NotNull Llama llama) {
+ super(llama);
+ }
+
+ @Override
+ @NotNull
+ public Llama getEntity() {
+ return (Llama) entity;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,112 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 10 Aug 2019 22:19:56 -0500
Subject: [PATCH] AFK API
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index d972cb242102a3ee7c017299aed64340628c79d8..972cca3e02296f94099f965a4f7662ec63a067ea 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3814,5 +3814,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @return True if Player uses Purpur Client
*/
public boolean usesPurpurClient();
+
+ /**
+ * Check if player is AFK
+ *
+ * @return True if AFK
+ */
+ boolean isAfk();
+
+ /**
+ * Set player as AFK
+ *
+ * @param setAfk Whether to set AFK or not
+ */
+ void setAfk(boolean setAfk);
+
+ /**
+ * Reset the idle timer back to 0
+ * @deprecated Use {@link #resetIdleDuration()} instead
+ */
+ void resetIdleTimer();
// Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/event/PlayerAFKEvent.java b/src/main/java/org/purpurmc/purpur/event/PlayerAFKEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..25e92af7710316ed2afedf846a59dbd672869b51
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/PlayerAFKEvent.java
@@ -0,0 +1,70 @@
+package org.purpurmc.purpur.event;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PlayerAFKEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private final boolean setAfk;
+ private boolean shouldKick;
+ private String broadcast;
+ private boolean cancel;
+
+ public PlayerAFKEvent(@NotNull Player player, boolean setAfk, boolean shouldKick, @Nullable String broadcast, boolean async) {
+ super(player, async);
+ this.setAfk = setAfk;
+ this.shouldKick = shouldKick;
+ this.broadcast = broadcast;
+ }
+
+ /**
+ * Whether player is going afk or coming back
+ *
+ * @return True if going afk. False is coming back
+ */
+ public boolean isGoingAfk() {
+ return setAfk;
+ }
+
+ public boolean shouldKick() {
+ return shouldKick;
+ }
+
+ public void setShouldKick(boolean shouldKick) {
+ this.shouldKick = shouldKick;
+ }
+
+ @Nullable
+ public String getBroadcastMsg() {
+ return broadcast;
+ }
+
+ public void setBroadcastMsg(@Nullable String broadcast) {
+ this.broadcast = broadcast;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancel;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 26 May 2019 15:18:40 -0500
Subject: [PATCH] Bring back server name
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 5d1b55fdbcbe63f6b42b694d05211a3cc691a09d..54f11593f4acfb89623cf1fad58819e001505fd1 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2910,4 +2910,15 @@ public final class Bukkit {
public static Server.Spigot spigot() {
return server.spigot();
}
+
+ // Purpur start
+ /**
+ * Get the name of this server
+ * @return the name of the server
+ */
+ @NotNull
+ public static String getServerName() {
+ return server.getServerName();
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index f5c3c1a0c11dd3518981ce3b86dba8ced8578d9c..1299cab5a4a0a017e0a1b792539d9b6fb8ef6c54 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2552,4 +2552,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
boolean isOwnedByCurrentRegion(@NotNull Entity entity);
// Paper end - Folia region threading API
+
+ // Purpur start
+ /**
+ * Get the name of this server
+ * @return the name of the server
+ */
+ @NotNull
+ String getServerName();
+ // Purpur end
}

View File

@@ -1,175 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 31 May 2019 00:08:28 -0500
Subject: [PATCH] ExecuteCommandEvent
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
index ac9a28922f8a556944a4c3649d74c32c622f0cb0..e842d13febca67ffa1c89fb2c1324d2609fb81fd 100644
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -143,6 +143,19 @@ public class SimpleCommandMap implements CommandMap {
return false;
}
+ // Purpur start
+ String[] parsedArgs = Arrays.copyOfRange(args, 1, args.length);
+ org.purpurmc.purpur.event.ExecuteCommandEvent event = new org.purpurmc.purpur.event.ExecuteCommandEvent(sender, target, sentCommandLabel, parsedArgs);
+ if (!event.callEvent()) {
+ return true; // cancelled
+ }
+
+ sender = event.getSender();
+ target = event.getCommand();
+ sentCommandLabel = event.getLabel();
+ parsedArgs = event.getArgs();
+ // Purpur end
+
// Paper start - Plugins do weird things to workaround normal registration
if (target.timings == null) {
target.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, target);
@@ -152,7 +165,7 @@ public class SimpleCommandMap implements CommandMap {
try {
try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources
// Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false)
- target.execute(sender, sentCommandLabel, Arrays.copyOfRange(args, 1, args.length));
+ target.execute(sender, sentCommandLabel, parsedArgs); // Purpur
} // target.timings.stopTiming(); // Spigot // Paper
} catch (CommandException ex) {
server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper
diff --git a/src/main/java/org/purpurmc/purpur/event/ExecuteCommandEvent.java b/src/main/java/org/purpurmc/purpur/event/ExecuteCommandEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc590c4d49d32f4365a50ceb5785e798702a8179
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/ExecuteCommandEvent.java
@@ -0,0 +1,130 @@
+package org.purpurmc.purpur.event;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * This event is called whenever someone runs a command
+ */
+public class ExecuteCommandEvent extends Event implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancel = false;
+ private CommandSender sender;
+ private Command command;
+ private String label;
+ private String[] args;
+
+ public ExecuteCommandEvent(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @Nullable String[] args) {
+ this.sender = sender;
+ this.command = command;
+ this.label = label;
+ this.args = args;
+ }
+
+ /**
+ * Gets the command that the player is attempting to execute.
+ *
+ * @return Command the player is attempting to execute
+ */
+ @NotNull
+ public Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Sets the command that the player will execute.
+ *
+ * @param command New command that the player will execute
+ * @throws IllegalArgumentException if command is null or empty
+ */
+ public void setCommand(@NotNull Command command) throws IllegalArgumentException {
+ Preconditions.checkArgument(command != null, "Command cannot be null");
+ this.command = command;
+ }
+
+ /**
+ * Gets the sender that this command will be executed as.
+ *
+ * @return Sender this command will be executed as
+ */
+ @NotNull
+ public CommandSender getSender() {
+ return sender;
+ }
+
+ /**
+ * Sets the sender that this command will be executed as.
+ *
+ * @param sender New sender which this event will execute as
+ * @throws IllegalArgumentException if the sender provided is null
+ */
+ public void setSender(@NotNull final CommandSender sender) throws IllegalArgumentException {
+ Preconditions.checkArgument(sender != null, "Sender cannot be null");
+ this.sender = sender;
+ }
+
+ /**
+ * Get the label used to execute this command
+ *
+ * @return Label used to execute this command
+ */
+ @NotNull
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Set the label used to execute this command
+ *
+ * @param label Label used
+ */
+ public void setLabel(@NotNull String label) {
+ this.label = label;
+ }
+
+ /**
+ * Get the args passed to the command
+ *
+ * @return Args passed to the command
+ */
+ @NotNull
+ public String[] getArgs() {
+ return args;
+ }
+
+ /**
+ * Set the args passed to the command
+ *
+ * @param args Args passed to the command
+ */
+ public void setArgs(@NotNull String[] args) {
+ this.args = args;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancel;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,42 +0,0 @@
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] Lagging threshold
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 54f11593f4acfb89623cf1fad58819e001505fd1..215647d7f5cc8487d6a173bc0160fec6db1971eb 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2920,5 +2920,14 @@ public final class Bukkit {
public static String getServerName() {
return server.getServerName();
}
+
+ /**
+ * 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 1299cab5a4a0a017e0a1b792539d9b6fb8ef6c54..7f9dc209c88a66bd2ee82cc62b948e827c6b1060 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2560,5 +2560,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
@NotNull
String getServerName();
+
+ /**
+ * Check if server is lagging according to laggy threshold setting
+ *
+ * @return True if lagging
+ */
+ boolean isLagging();
// Purpur end
}

View File

@@ -1,97 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 5 Jul 2019 18:21:15 -0500
Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent
diff --git a/src/main/java/org/purpurmc/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java b/src/main/java/org/purpurmc/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..519809eab5d926dc7b0a7bad5d446d0defc099dc
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/PlayerSetSpawnerTypeWithEggEvent.java
@@ -0,0 +1,85 @@
+package org.purpurmc.purpur.event;
+
+import org.bukkit.block.Block;
+import org.bukkit.block.CreatureSpawner;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+public class PlayerSetSpawnerTypeWithEggEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private final Block block;
+ private final CreatureSpawner spawner;
+ private EntityType type;
+ private boolean cancel;
+
+ public PlayerSetSpawnerTypeWithEggEvent(@NotNull Player player, @NotNull Block block, @NotNull CreatureSpawner spawner, @NotNull EntityType type) {
+ super(player);
+ this.block = block;
+ this.spawner = spawner;
+ this.type = type;
+ }
+
+ /**
+ * Get the spawner Block in the world
+ *
+ * @return Spawner Block
+ */
+ @NotNull
+ public Block getBlock() {
+ return block;
+ }
+
+ /**
+ * Get the spawner state
+ *
+ * @return Spawner state
+ */
+ @NotNull
+ public CreatureSpawner getSpawner() {
+ return spawner;
+ }
+
+ /**
+ * Gets the EntityType being set on the spawner
+ *
+ * @return EntityType being set
+ */
+ @NotNull
+ public EntityType getEntityType() {
+ return type;
+ }
+
+ /**
+ * Sets the EntityType being set on the spawner
+ *
+ * @param type EntityType to set
+ */
+ public void setEntityType(@NotNull EntityType type) {
+ this.type = type;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancel;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,124 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 19 Apr 2020 00:25:09 -0500
Subject: [PATCH] Anvil API
diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java
index c60be4fd24c7fdf65251dd6169e5e1ac3b588d95..569deccd2f1cf21da9b5906433ac493c1f2081be 100644
--- a/src/main/java/org/bukkit/inventory/AnvilInventory.java
+++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java
@@ -123,4 +123,14 @@ public interface AnvilInventory extends Inventory {
setItem(2, result);
}
// Paper end
+
+ // Purpur start
+ boolean canBypassCost();
+
+ void setBypassCost(boolean bypassCost);
+
+ boolean canDoUnsafeEnchants();
+
+ void setDoUnsafeEnchants(boolean canDoUnsafeEnchants);
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/event/inventory/AnvilTakeResultEvent.java b/src/main/java/org/purpurmc/purpur/event/inventory/AnvilTakeResultEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b363c91a29f826910db22f2643decf996a067ab5
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/inventory/AnvilTakeResultEvent.java
@@ -0,0 +1,52 @@
+package org.purpurmc.purpur.event.inventory;
+
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.inventory.InventoryEvent;
+import org.bukkit.inventory.AnvilInventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player takes the result item out of an anvil
+ */
+public class AnvilTakeResultEvent extends InventoryEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final Player player;
+ private final ItemStack result;
+
+ public AnvilTakeResultEvent(@NotNull HumanEntity player, @NotNull InventoryView view, @NotNull ItemStack result) {
+ super(view);
+ this.player = (Player) player;
+ this.result = result;
+ }
+
+ @NotNull
+ public Player getPlayer() {
+ return player;
+ }
+
+ @NotNull
+ public ItemStack getResult() {
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public AnvilInventory getInventory() {
+ return (AnvilInventory) super.getInventory();
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/inventory/AnvilUpdateResultEvent.java b/src/main/java/org/purpurmc/purpur/event/inventory/AnvilUpdateResultEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd6a5a3589d436c2aaf988fd305899695799d3bb
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/inventory/AnvilUpdateResultEvent.java
@@ -0,0 +1,35 @@
+package org.purpurmc.purpur.event.inventory;
+
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.inventory.InventoryEvent;
+import org.bukkit.inventory.AnvilInventory;
+import org.bukkit.inventory.InventoryView;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when anvil slots change, triggering the result slot to be updated
+ */
+public class AnvilUpdateResultEvent extends InventoryEvent {
+ private static final HandlerList handlers = new HandlerList();
+
+ public AnvilUpdateResultEvent(@NotNull InventoryView view) {
+ super(view);
+ }
+
+ @NotNull
+ @Override
+ public AnvilInventory getInventory() {
+ return (AnvilInventory) super.getInventory();
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 2 Oct 2020 17:43:24 -0500
Subject: [PATCH] Add predicate to recipe's ExactChoice ingredient
diff --git a/src/main/java/org/bukkit/inventory/RecipeChoice.java b/src/main/java/org/bukkit/inventory/RecipeChoice.java
index db8bcc66bdc4bedfffb4705db6338eda4c0ad29a..feda3ddfaaf37b6ee218a0e0b1fbc199899bd364 100644
--- a/src/main/java/org/bukkit/inventory/RecipeChoice.java
+++ b/src/main/java/org/bukkit/inventory/RecipeChoice.java
@@ -10,6 +10,7 @@ import java.util.function.Predicate;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable; // Purpur
/**
* Represents a potential item match within a recipe. All choices within a
@@ -150,6 +151,7 @@ public interface RecipeChoice extends Predicate<ItemStack>, Cloneable {
public static class ExactChoice implements RecipeChoice {
private List<ItemStack> choices;
+ private Predicate<ItemStack> predicate; // Purpur
public ExactChoice(@NotNull ItemStack stack) {
this(Arrays.asList(stack));
@@ -194,6 +196,7 @@ public interface RecipeChoice extends Predicate<ItemStack>, Cloneable {
@Override
public boolean test(@NotNull ItemStack t) {
+ if (predicate != null) return predicate.test(t); // Purpur
for (ItemStack match : choices) {
if (t.isSimilar(match)) {
return true;
@@ -203,6 +206,17 @@ public interface RecipeChoice extends Predicate<ItemStack>, Cloneable {
return false;
}
+ // Purpur start
+ @Nullable
+ public Predicate<ItemStack> getPredicate() {
+ return predicate;
+ }
+
+ public void setPredicate(@Nullable Predicate<ItemStack> predicate) {
+ this.predicate = predicate;
+ }
+ // Purpur end
+
@Override
public int hashCode() {
int hash = 7;

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Tue, 8 Dec 2020 17:15:15 -0500
Subject: [PATCH] Rabid Wolf API
diff --git a/src/main/java/org/bukkit/entity/Wolf.java b/src/main/java/org/bukkit/entity/Wolf.java
index 4b84c04675775e2a606630b00de8afe51665cebc..ccbaf40a3131f477b4be2264401ad893725c1162 100644
--- a/src/main/java/org/bukkit/entity/Wolf.java
+++ b/src/main/java/org/bukkit/entity/Wolf.java
@@ -112,4 +112,20 @@ public interface Wolf extends Tameable, Sittable, io.papermc.paper.entity.Collar
return variant;
}
}
+
+ // Purpur start
+ /**
+ * Checks if this wolf is rabid
+ *
+ * @return whether the wolf is rabid
+ */
+ public boolean isRabid();
+
+ /**
+ * Sets this wolf to be rabid or not
+ *
+ * @param rabid whether the wolf should be rabid
+ */
+ public void setRabid(boolean rabid);
+ // Purpur end
}

View File

@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Wed, 23 Dec 2020 00:43:27 -0600
Subject: [PATCH] PlayerBookTooLargeEvent
diff --git a/src/main/java/org/purpurmc/purpur/event/player/PlayerBookTooLargeEvent.java b/src/main/java/org/purpurmc/purpur/event/player/PlayerBookTooLargeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c88394336bc9ab0f66a2af24d393f4a176a234d5
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/player/PlayerBookTooLargeEvent.java
@@ -0,0 +1,65 @@
+package org.purpurmc.purpur.event.player;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player tries to bypass book limitations
+ */
+public class PlayerBookTooLargeEvent extends PlayerEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final ItemStack book;
+ private boolean kickPlayer = true;
+
+ /**
+ * @param player The player
+ * @param book The book
+ */
+ public PlayerBookTooLargeEvent(@NotNull Player player, @NotNull ItemStack book) {
+ super(player, !Bukkit.isPrimaryThread());
+ this.book = book;
+ }
+
+ /**
+ * Get the book containing the wanted edits
+ *
+ * @return The book
+ */
+ @NotNull
+ public ItemStack getBook() {
+ return book;
+ }
+
+ /**
+ * Whether server should kick the player or not
+ *
+ * @return True to kick player
+ */
+ public boolean shouldKickPlayer() {
+ return kickPlayer;
+ }
+
+ /**
+ * Whether server should kick the player or not
+ *
+ * @param kickPlayer True to kick player
+ */
+ public void setShouldKickPlayer(boolean kickPlayer) {
+ this.kickPlayer = kickPlayer;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 24 Dec 2020 11:00:04 -0600
Subject: [PATCH] Full netherite armor grants fire resistance
diff --git a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java
index c9f395064656dd0126410eb3c6e197baa450c063..13156a12e5df50cdc1e465dc0bd9d94108275629 100644
--- a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java
@@ -217,6 +217,12 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable
* When all effects are removed due to a bucket of milk.
*/
MILK,
+ // Purpur start
+ /**
+ * When a player wears full netherite armor
+ */
+ NETHERITE_ARMOR,
+ // Purpur end
/**
* When a player gets bad omen after killing a patrol captain.
*/

View File

@@ -1,141 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 9 Jan 2021 15:26:04 +0100
Subject: [PATCH] Add EntityTeleportHinderedEvent
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/EntityTeleportHinderedEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/EntityTeleportHinderedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c66eb163877e872f234d86dc244cab7efeb818cd
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/EntityTeleportHinderedEvent.java
@@ -0,0 +1,117 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Fired when an entity is hindered from teleporting.
+ */
+public class EntityTeleportHinderedEvent extends EntityEvent {
+ private static final HandlerList handlers = new HandlerList();
+
+ @NotNull
+ private final Reason reason;
+
+ @Nullable
+ private final TeleportCause teleportCause;
+
+ private boolean retry = false;
+
+ public EntityTeleportHinderedEvent(@NotNull Entity what, @NotNull Reason reason,
+ @Nullable TeleportCause teleportCause) {
+ super(what);
+ this.reason = reason;
+ this.teleportCause = teleportCause;
+ }
+
+ /**
+ * @return why the teleport was hindered.
+ */
+ @NotNull
+ public Reason getReason() {
+ return reason;
+ }
+
+ /**
+ * @return why the teleport occurred if cause was given, otherwise {@code null}.
+ */
+ @Nullable
+ public TeleportCause getTeleportCause() {
+ return teleportCause;
+ }
+
+ /**
+ * Whether the teleport should be retried.
+ * <p>
+ * Note that this can put the server in a never-ending loop of trying to teleport someone resulting in a stack
+ * overflow. Do not retry more than necessary.
+ * </p>
+ *
+ * @return whether the teleport should be retried.
+ */
+ public boolean shouldRetry() {
+ return retry;
+ }
+
+ /**
+ * Sets whether the teleport should be retried.
+ * <p>
+ * Note that this can put the server in a never-ending loop of trying to teleport someone resulting in a stack
+ * overflow. Do not retry more than necessary.
+ * </p>
+ *
+ * @param retry whether the teleport should be retried.
+ */
+ public void setShouldRetry(boolean retry) {
+ this.retry = retry;
+ }
+
+ /**
+ * Calls the event and tests if should retry.
+ *
+ * @return whether the teleport should be retried.
+ */
+ @Override
+ public boolean callEvent() {
+ super.callEvent();
+ return shouldRetry();
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Reason for hindrance in teleports.
+ */
+ public enum Reason {
+ /**
+ * The teleported entity is a passenger of another entity.
+ */
+ IS_PASSENGER,
+
+ /**
+ * The teleported entity has passengers.
+ */
+ IS_VEHICLE,
+
+ /**
+ * The teleport event was cancelled.
+ * <p>
+ * This is only caused by players teleporting.
+ * </p>
+ */
+ EVENT_CANCELLED,
+ }
+}

View File

@@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Tue, 25 May 2021 16:30:30 -0400
Subject: [PATCH] API for any mob to burn daylight
Co-authored by: Encode42 <me@encode42.dev>
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 50344412a04f3008439e337ecf9dd09c7f853bc9..f482467ae784b134da97eb38afb7f12585520297 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -1185,5 +1185,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* @return True if ridable in water
*/
boolean isRidableInWater();
+
+ /**
+ * Checks if the entity is in daylight
+ *
+ * @return True if in daylight
+ */
+ boolean isInDaylight();
// Purpur end
}
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index aba9952b2256b058eb413ce93f3305c861a200db..61a046584acf48693489ff551a0dd4c4b16af9ff 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -1455,5 +1455,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
* @param slot Equipment slot to play break animation for
*/
void broadcastItemBreak(@NotNull org.bukkit.inventory.EquipmentSlot slot);
+
+ /**
+ * If this mob will burn in the sunlight
+ *
+ * @return True if mob will burn in sunlight
+ */
+ boolean shouldBurnInDay();
+
+ /**
+ * Set if this mob should burn in the sunlight
+ *
+ * @param shouldBurnInDay True to burn in sunlight
+ */
+ void setShouldBurnInDay(boolean shouldBurnInDay);
// Purpur end
}

View File

@@ -1,77 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 30 Jun 2021 17:44:27 -0500
Subject: [PATCH] Fix default permission system
diff --git a/src/main/java/org/bukkit/permissions/PermissibleBase.java b/src/main/java/org/bukkit/permissions/PermissibleBase.java
index cd3296fea01648592d2af89b3d80135acb6d0958..45797a6fbae1d8edc4211cb30def24ad4f59bd49 100644
--- a/src/main/java/org/bukkit/permissions/PermissibleBase.java
+++ b/src/main/java/org/bukkit/permissions/PermissibleBase.java
@@ -168,7 +168,7 @@ public class PermissibleBase implements Permissible {
for (Permission perm : defaults) {
String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH);
- permissions.put(name, new PermissionAttachmentInfo(parent, name, null, true));
+ permissions.put(name, new PermissionAttachmentInfo(parent, name, null, perm.getDefault().getValue(isOp()))); // Purpur
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
calculateChildPermissions(perm.getChildren(), false, null);
}
@@ -196,7 +196,7 @@ public class PermissibleBase implements Permissible {
String name = entry.getKey();
Permission perm = Bukkit.getServer().getPluginManager().getPermission(name);
- boolean value = entry.getValue() ^ invert;
+ boolean value = (entry.getValue() == null && perm != null ? perm.getDefault().getValue(isOp()) : entry.getValue()) ^ invert; // Purpur
String lname = name.toLowerCase(java.util.Locale.ENGLISH);
permissions.put(lname, new PermissionAttachmentInfo(parent, lname, attachment, value));
diff --git a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
index 8e481e3815f5645ee92f0d229e5ff25c8fc9a6c2..10627d2a11251a8cb01bbc3f6242d66f3505a16e 100644
--- a/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
+++ b/src/main/java/org/bukkit/util/permissions/DefaultPermissions.java
@@ -31,7 +31,7 @@ public final class DefaultPermissions {
if (withLegacy) {
Permission legacy = new Permission(LEGACY_PREFIX + result.getName(), result.getDescription(), PermissionDefault.FALSE);
- legacy.getChildren().put(result.getName(), true);
+ legacy.getChildren().put(result.getName(), null); // Purpur
registerPermission(perm, false);
}
@@ -40,7 +40,7 @@ public final class DefaultPermissions {
@NotNull
public static Permission registerPermission(@NotNull Permission perm, @NotNull Permission parent) {
- parent.getChildren().put(perm.getName(), true);
+ parent.getChildren().put(perm.getName(), null); // Purpur
return registerPermission(perm);
}
@@ -53,7 +53,7 @@ public final class DefaultPermissions {
@NotNull
public static Permission registerPermission(@NotNull String name, @Nullable String desc, @NotNull Permission parent) {
Permission perm = registerPermission(name, desc);
- parent.getChildren().put(perm.getName(), true);
+ parent.getChildren().put(perm.getName(), null); // Purpur
return perm;
}
@@ -66,7 +66,7 @@ public final class DefaultPermissions {
@NotNull
public static Permission registerPermission(@NotNull String name, @Nullable String desc, @Nullable PermissionDefault def, @NotNull Permission parent) {
Permission perm = registerPermission(name, desc, def);
- parent.getChildren().put(perm.getName(), true);
+ parent.getChildren().put(perm.getName(), null); // Purpur
return perm;
}
@@ -79,7 +79,7 @@ public final class DefaultPermissions {
@NotNull
public static Permission registerPermission(@NotNull String name, @Nullable String desc, @Nullable PermissionDefault def, @Nullable Map<String, Boolean> children, @NotNull Permission parent) {
Permission perm = registerPermission(name, desc, def, children);
- parent.getChildren().put(perm.getName(), true);
+ parent.getChildren().put(perm.getName(), null); // Purpur
return perm;
}

View File

@@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 3 Jul 2021 18:45:01 -0500
Subject: [PATCH] Summoner API
diff --git a/src/main/java/org/bukkit/entity/IronGolem.java b/src/main/java/org/bukkit/entity/IronGolem.java
index 655e37cb3a09610a3f3df805d6dcad17d722da62..09fd716c8fc9ea34a1cbf87bcbe22df035422a51 100644
--- a/src/main/java/org/bukkit/entity/IronGolem.java
+++ b/src/main/java/org/bukkit/entity/IronGolem.java
@@ -19,4 +19,20 @@ public interface IronGolem extends Golem {
* player created, false if you want it to be a natural village golem.
*/
public void setPlayerCreated(boolean playerCreated);
+
+ // Purpur start
+ /**
+ * Get the player that summoned this iron golem
+ *
+ * @return UUID of summoner
+ */
+ @org.jetbrains.annotations.Nullable java.util.UUID getSummoner();
+
+ /**
+ * Set the player that summoned this iron golem
+ *
+ * @param summoner UUID of summoner
+ */
+ void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner);
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java
index 7fbfdb07585c7b28acea1f0c1f58ada0cc744441..21fcca092e2e31baa5ece0de9e44e3fade8c7123 100644
--- a/src/main/java/org/bukkit/entity/Snowman.java
+++ b/src/main/java/org/bukkit/entity/Snowman.java
@@ -23,4 +23,20 @@ public interface Snowman extends Golem, RangedEntity, io.papermc.paper.entity.Sh
* @param derpMode True to remove the pumpkin, false to add a pumpkin
*/
void setDerp(boolean derpMode);
+
+ // Purpur start
+ /**
+ * Get the player that summoned this snowman
+ *
+ * @return UUID of summoner
+ */
+ @org.jetbrains.annotations.Nullable java.util.UUID getSummoner();
+
+ /**
+ * Set the player that summoned this snowman
+ *
+ * @param summoner UUID of summoner
+ */
+ void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner);
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/entity/Wither.java b/src/main/java/org/bukkit/entity/Wither.java
index 14543c2238b45c526dd9aebea2aa5c22f5df54dc..5312daf33405704c74e2c9e109754285ea6cf734 100644
--- a/src/main/java/org/bukkit/entity/Wither.java
+++ b/src/main/java/org/bukkit/entity/Wither.java
@@ -107,4 +107,20 @@ public interface Wither extends Monster, Boss, com.destroystokyo.paper.entity.Ra
*/
void enterInvulnerabilityPhase();
// Paper end
+
+ // Purpur start
+ /**
+ * Get the player that summoned this wither
+ *
+ * @return UUID of summoner
+ */
+ @org.jetbrains.annotations.Nullable java.util.UUID getSummoner();
+
+ /**
+ * Set the player that summoned this wither
+ *
+ * @param summoner UUID of summoner
+ */
+ void setSummoner(@org.jetbrains.annotations.Nullable java.util.UUID summoner);
+ // Purpur end
}

View File

@@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 15 Jul 2021 23:43:04 -0500
Subject: [PATCH] Clean up version command output
diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
index a736d7bcdc5861a01b66ba36158db1c716339346..22fc165fd9c95f0f3ae1be7a0857e48cc50fad5b 100644
--- a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
@@ -26,6 +26,12 @@ public interface VersionFetcher {
@NotNull
Component getVersionMessage(@NotNull String serverVersion);
+ // Purpur start
+ default int distance() {
+ return 0;
+ }
+ // Purpur end
+
class DummyVersionFetcher implements VersionFetcher {
@Override
diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
index fd5d9881abfd930bb883120f018f76dc78b62b14..d3dadad49df09e85c724c93e8cc88da2c985e9b4 100644
--- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java
+++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
@@ -214,7 +214,7 @@ public class VersionCommand extends BukkitCommand {
String version = Bukkit.getVersion();
// Paper start
if (version.startsWith("null")) { // running from ide?
- setVersionMessage(Component.text("Unknown version, custom build?", NamedTextColor.YELLOW));
+ setVersionMessage(Component.text("* Unknown version, custom build?", NamedTextColor.RED)); // Purpur
return;
}
setVersionMessage(getVersionFetcher().getVersionMessage(version));
@@ -255,9 +255,11 @@ public class VersionCommand extends BukkitCommand {
// Paper start
private void setVersionMessage(final @NotNull Component msg) {
lastCheck = System.currentTimeMillis();
- final Component message = Component.textOfChildren(
- Component.text(Bukkit.getVersionMessage(), NamedTextColor.WHITE),
- Component.newline(),
+ // Purpur start
+ int distance = getVersionFetcher().distance();
+ final Component message = Component.join(net.kyori.adventure.text.JoinConfiguration.separator(Component.newline()),
+ ChatColor.parseMM("<grey>Current: %s%s*", distance == 0 ? "<green>" : distance > 0 ? "<yellow>" : "<red>", Bukkit.getVersion()),
+ // Purpur end
msg
);
this.versionMessage = Component.text()

View File

@@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DoctaEnkoda <bierquejason@gmail.com>
Date: Mon, 9 Aug 2021 13:22:03 +0200
Subject: [PATCH] Added the ability to add combustible items
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 215647d7f5cc8487d6a173bc0160fec6db1971eb..7bc4e5e9947ab646707a5c0b39c70c0cc6606bd8 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2929,5 +2929,24 @@ public final class Bukkit {
public static boolean isLagging() {
return server.isLagging();
}
+
+ /**
+ * Add an Item as fuel for furnaces
+ *
+ * @param material The material that will be the fuel
+ * @param burnTime The time (in ticks) this item will burn for
+ */
+ public static void addFuel(@NotNull Material material, int burnTime) {
+ server.addFuel(material, burnTime);
+ }
+
+ /**
+ * Remove an item as fuel for furnaces
+ *
+ * @param material The material that will no longer be a fuel
+ */
+ public static void removeFuel(@NotNull Material material) {
+ server.removeFuel(material);
+ }
// Purpur end
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 7f9dc209c88a66bd2ee82cc62b948e827c6b1060..fa926319ff033768d78508491e072efec1dcbc9f 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2567,5 +2567,20 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @return True if lagging
*/
boolean isLagging();
+
+ /**
+ * Add an Item as fuel for furnaces
+ *
+ * @param material The material that will be the fuel
+ * @param burnTime The time (in ticks) this item will burn for
+ */
+ public void addFuel(@NotNull Material material, int burnTime);
+
+ /**
+ * Remove an item as fuel for furnaces
+ *
+ * @param material The material that will no longer be a fuel
+ */
+ public void removeFuel(@NotNull Material material);
// Purpur end
}

View File

@@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Mon, 27 Dec 2021 08:10:50 -0600
Subject: [PATCH] Grindstone API
diff --git a/src/main/java/org/purpurmc/purpur/event/inventory/GrindstoneTakeResultEvent.java b/src/main/java/org/purpurmc/purpur/event/inventory/GrindstoneTakeResultEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..eebb5d124456b8209d1b8e8cc4cb772dd3714f04
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/inventory/GrindstoneTakeResultEvent.java
@@ -0,0 +1,72 @@
+package org.purpurmc.purpur.event.inventory;
+
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.inventory.InventoryEvent;
+import org.bukkit.inventory.GrindstoneInventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player takes the result item out of a Grindstone
+ */
+public class GrindstoneTakeResultEvent extends InventoryEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final Player player;
+ private final ItemStack result;
+ private int experienceAmount;
+
+ public GrindstoneTakeResultEvent(@NotNull HumanEntity player, @NotNull InventoryView view, @NotNull ItemStack result, int experienceAmount) {
+ super(view);
+ this.player = (Player) player;
+ this.result = result;
+ this.experienceAmount = experienceAmount;
+ }
+
+ @NotNull
+ public Player getPlayer() {
+ return player;
+ }
+
+ @NotNull
+ public ItemStack getResult() {
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public GrindstoneInventory getInventory() {
+ return (GrindstoneInventory) super.getInventory();
+ }
+
+ /**
+ * Get the amount of experience this transaction will give
+ *
+ * @return Amount of experience to give
+ */
+ public int getExperienceAmount() {
+ return this.experienceAmount;
+ }
+
+ /**
+ * Set the amount of experience this transaction will give
+ *
+ * @param experienceAmount Amount of experience to give
+ */
+ public void setExperienceAmount(int experienceAmount) {
+ this.experienceAmount = experienceAmount;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Mon, 3 Jan 2022 02:00:50 -0600
Subject: [PATCH] Shears can have looting enchantment
diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java b/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java
index 5831ffe24eed01311c71989dcb1830dbc395607b..45f5493eebfecf56b7c0ef4659c078dfc62c0612 100644
--- a/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java
+++ b/src/main/java/org/bukkit/enchantments/EnchantmentTarget.java
@@ -238,6 +238,16 @@ public enum EnchantmentTarget {
public boolean includes(@NotNull Material item) {
return item.equals(Material.BOW) || item.equals(Material.CROSSBOW);
}
+ },
+
+ /**
+ * Allow the Enchantment to be placed on shears.
+ */
+ WEAPON_AND_SHEARS {
+ @Override
+ public boolean includes(@NotNull Material item) {
+ return WEAPON.includes(item) || item.equals(Material.SHEARS);
+ }
// Purpur end
};

View File

@@ -1,25 +0,0 @@
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] Lobotomize stuck villagers
diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java
index 3bc24457d143449e6a338d79becf7c39b9f81054..4a5edf4e72e81b22c1abb2ade244f7f4292e993c 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
}

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sat, 9 Jul 2022 00:57:26 -0500
Subject: [PATCH] Add local difficulty api
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 97f97ea5c6aa513c439f86a9c82821e0f7d9cd1e..099516b90c504205b894b387542221e8c0c98b40 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -4249,6 +4249,16 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@Nullable
public DragonBattle getEnderDragonBattle();
+ // Purpur start
+ /**
+ * Gets the local difficulty (based on inhabited time) at a location
+ *
+ * @param location Location to check
+ * @return The local difficulty
+ */
+ public float getLocalDifficultyAt(@NotNull Location location);
+ // Purpur end
+
/**
* Get all {@link FeatureFlag} enabled in this world.
*

View File

@@ -1,168 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 1 Jul 2022 04:03:26 -0500
Subject: [PATCH] Remove Timings
diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java
index 8f29c1561ba5916cb5634392edd8bd2a5a294a51..6fbc64e0f214d0c8e5afcbe385e414a4e1fe1c72 100644
--- a/src/main/java/co/aikar/timings/TimedEventExecutor.java
+++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java
@@ -77,9 +77,9 @@ public class TimedEventExecutor implements EventExecutor {
executor.execute(listener, event);
return;
}
- try (Timing ignored = timings.startTiming()){
+ //try (Timing ignored = timings.startTiming()){ // Purpur
executor.execute(listener, event);
- }
+ //} // Purpur
}
@Override
diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java
index 7514fad26f955329f8bf17ff17db75f0c8301ee5..1d866e980abc542bdfee1ce082cd9cdd7761e9f7 100644
--- a/src/main/java/co/aikar/timings/Timing.java
+++ b/src/main/java/co/aikar/timings/Timing.java
@@ -39,6 +39,7 @@ public interface Timing extends AutoCloseable {
* @return Timing
*/
@NotNull
+ @io.papermc.paper.annotation.DoNotUse // Purpur
Timing startTiming();
/**
@@ -46,6 +47,7 @@ public interface Timing extends AutoCloseable {
*
* Will automatically be called when this Timing is used with try-with-resources
*/
+ @io.papermc.paper.annotation.DoNotUse // Purpur
void stopTiming();
/**
@@ -56,6 +58,7 @@ public interface Timing extends AutoCloseable {
* @return Timing
*/
@NotNull
+ @io.papermc.paper.annotation.DoNotUse // Purpur
Timing startTimingIfSync();
/**
@@ -65,12 +68,14 @@ public interface Timing extends AutoCloseable {
*
* But only if we are on the primary thread.
*/
+ @io.papermc.paper.annotation.DoNotUse // Purpur
void stopTimingIfSync();
/**
* @deprecated Doesn't do anything - Removed
*/
@Deprecated
+ @io.papermc.paper.annotation.DoNotUse // Purpur
void abort();
/**
@@ -82,5 +87,6 @@ public interface Timing extends AutoCloseable {
TimingHandler getTimingHandler();
@Override
+ @io.papermc.paper.annotation.DoNotUse // Purpur
void close();
}
diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java
index 9812d668ad945aba486fbf6d5bf83c4292cb5d03..752d54830aa8baa1450bf72da03ae55ed30293c2 100644
--- a/src/main/java/co/aikar/timings/Timings.java
+++ b/src/main/java/co/aikar/timings/Timings.java
@@ -124,7 +124,7 @@ public final class Timings {
@NotNull
public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) {
Timing timing = of(plugin, name, groupHandler);
- timing.startTiming();
+ //timing.startTiming(); // Purpur
return timing;
}
@@ -145,9 +145,11 @@ public final class Timings {
* @param enabled Should timings be reported
*/
public static void setTimingsEnabled(boolean enabled) {
- timingsEnabled = enabled;
- warnAboutDeprecationOnEnable();
- reset();
+ // Purpur start - we don't do that here...
+ timingsEnabled = false;
+ //warnAboutDeprecationOnEnable();
+ //reset();
+ // Purpur end
}
private static void warnAboutDeprecationOnEnable() {
diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java
index e801e79fa57c44b2e5d359647c920f88064826f1..1abfcee0f6d632f4cd8d74b4994a90c9ea9d254c 100644
--- a/src/main/java/co/aikar/timings/TimingsCommand.java
+++ b/src/main/java/co/aikar/timings/TimingsCommand.java
@@ -45,7 +45,7 @@ public class TimingsCommand extends BukkitCommand {
public TimingsCommand(@NotNull String name) {
super(name);
this.description = "Manages Spigot Timings data to see performance of the server.";
- this.usageMessage = "/timings <reset|report|on|off|verbon|verboff>";
+ this.usageMessage = "/timings";// <reset|report|on|off|verbon|verboff>"; // Purpur
this.setPermission("bukkit.command.timings");
}
@@ -54,8 +54,12 @@ public class TimingsCommand extends BukkitCommand {
if (!testPermission(sender)) {
return true;
}
- if (false) {
- sender.sendMessage(Timings.deprecationMessage());
+ if (true) {
+ net.kyori.adventure.text.minimessage.MiniMessage mm = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage();
+ sender.sendMessage(mm.deserialize("<gold>Purpur has removed timings to save your performance. Please use <click:suggest_command:'/spark'><grey>/spark</grey></click> instead"));
+ sender.sendMessage(mm.deserialize("<gold>For more information, view its documentation at"));
+ sender.sendMessage(mm.deserialize("<gold><click:open_url:'https://spark.lucko.me/docs/Command-Usage'>https://spark.lucko.me/docs/Command-Usage</click>"));
+ return true;
}
if (args.length < 1) {
sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED));
@@ -115,7 +119,7 @@ public class TimingsCommand extends BukkitCommand {
Preconditions.checkNotNull(args, "Arguments cannot be null");
Preconditions.checkNotNull(alias, "Alias cannot be null");
- if (args.length == 1) {
+ if (false && args.length == 1) { // Purpur
return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS,
new ArrayList<String>(TIMINGS_SUBCOMMANDS.size()));
}
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
index e842d13febca67ffa1c89fb2c1324d2609fb81fd..5349f16136d9348c374a7dfe5b89a71dfcb0e66d 100644
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -163,10 +163,10 @@ public class SimpleCommandMap implements CommandMap {
// Paper end
try {
- try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources
+ //try (co.aikar.timings.Timing ignored = target.timings.startTiming()) { // Paper - use try with resources // Purpur
// Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false)
target.execute(sender, sentCommandLabel, parsedArgs); // Purpur
- } // target.timings.stopTiming(); // Spigot // Paper
+ //} // target.timings.stopTiming(); // Spigot // Paper // Purpur
} catch (CommandException ex) {
server.getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args))); // Paper
//target.timings.stopTiming(); // Spigot // Paper
diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java
index 12946bd55fcf7c40d39081779a7fa30049ee6165..9c2d605c50cbf9aefa56ec209df9f6cea1392e89 100644
--- a/src/main/java/org/spigotmc/CustomTimingsHandler.java
+++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java
@@ -61,7 +61,7 @@ public final class CustomTimingsHandler {
handler = timing;
}
- public void startTiming() { handler.startTiming(); }
- public void stopTiming() { handler.stopTiming(); }
+ public void startTiming() { /*handler.startTiming();*/ } // Purpur
+ public void stopTiming() { /*handler.stopTiming();*/ } // Purpur
}

View File

@@ -1,179 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Mon, 25 Jul 2022 19:33:49 +0200
Subject: [PATCH] Add Bee API
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/BeeFoundFlowerEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/BeeFoundFlowerEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..833f46d1941f377765132fc528c45567ee0290d2
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/BeeFoundFlowerEvent.java
@@ -0,0 +1,48 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Bee;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when a bee targets a flower
+ */
+public class BeeFoundFlowerEvent extends EntityEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final Location location;
+
+ public BeeFoundFlowerEvent(@NotNull Bee bee, @Nullable Location location) {
+ super(bee);
+ this.location = location;
+ }
+
+ @Override
+ @NotNull
+ public Bee getEntity() {
+ return (Bee) super.getEntity();
+ }
+
+ /**
+ * Returns the location of the flower that the bee targets
+ *
+ * @return The location of the flower
+ */
+ @Nullable
+ public Location getLocation() {
+ return location;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/BeeStartedPollinatingEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/BeeStartedPollinatingEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae0bb654745724889c67fae9072ae90ea3778ba4
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/BeeStartedPollinatingEvent.java
@@ -0,0 +1,47 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Bee;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a bee starts pollinating
+ */
+public class BeeStartedPollinatingEvent extends EntityEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final Location location;
+
+ public BeeStartedPollinatingEvent(@NotNull Bee bee, @NotNull Location location) {
+ super(bee);
+ this.location = location;
+ }
+
+ @Override
+ @NotNull
+ public Bee getEntity() {
+ return (Bee) super.getEntity();
+ }
+
+ /**
+ * Returns the location of the flower that the bee pollinates
+ *
+ * @return The location of the flower
+ */
+ @NotNull
+ public Location getLocation() {
+ return this.location;
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/BeeStopPollinatingEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/BeeStopPollinatingEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff3c9f075be2f624af8b0ce5fffc5ea69a41f32e
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/BeeStopPollinatingEvent.java
@@ -0,0 +1,60 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Bee;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when a bee stops pollinating
+ */
+public class BeeStopPollinatingEvent extends EntityEvent {
+ private static final HandlerList handlers = new HandlerList();
+ private final Location location;
+ private final boolean success;
+
+ public BeeStopPollinatingEvent(@NotNull Bee bee, @Nullable Location location, boolean success) {
+ super(bee);
+ this.location = location;
+ this.success = success;
+ }
+
+ @Override
+ @NotNull
+ public Bee getEntity() {
+ return (Bee) super.getEntity();
+ }
+
+ /**
+ * Returns the location of the flower that the bee stopped pollinating
+ *
+ * @return The location of the flower
+ */
+ @Nullable
+ public Location getLocation() {
+ return location;
+ }
+
+ /**
+ * Returns whether the bee successfully pollinated the flower
+ *
+ * @return True if the pollination was successful
+ */
+ public boolean wasSuccessful() {
+ return success;
+ }
+
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,341 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: YouHaveTrouble <youhavetrouble@youhavetrouble.me>
Date: Sat, 23 Jul 2022 14:40:17 +0200
Subject: [PATCH] Debug Marker API
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 7bc4e5e9947ab646707a5c0b39c70c0cc6606bd8..70ef8f63ab79e102cb4326c21cc344488f4fbdd3 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2948,5 +2948,89 @@ public final class Bukkit {
public static void removeFuel(@NotNull Material material) {
server.removeFuel(material);
}
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration) {
+ server.sendBlockHighlight(location, duration);
+ }
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration, int argb) {
+ server.sendBlockHighlight(location, duration, argb);
+ }
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text) {
+ server.sendBlockHighlight(location, duration, text);
+ }
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, int argb) {
+ server.sendBlockHighlight(location, duration, text, argb);
+ }
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration, @NotNull org.bukkit.Color color, int transparency) {
+ server.sendBlockHighlight(location, duration, color, transparency);
+ }
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ public static void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, @NotNull org.bukkit.Color color, int transparency) {
+ server.sendBlockHighlight(location, duration, text, color, transparency);
+ }
+
+ /**
+ * Clears all debug block highlights for all players on the server.
+ */
+ public static void clearBlockHighlights() {
+ server.clearBlockHighlights();
+ }
// Purpur end
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index fa926319ff033768d78508491e072efec1dcbc9f..320422ff95773efa01e8205edcc5c6c9a84d5ecd 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2582,5 +2582,75 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @param material The material that will no longer be a fuel
*/
public void removeFuel(@NotNull Material material);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on the server.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Clears all debug block highlights for all players on the server.
+ */
+ void clearBlockHighlights();
// Purpur end
}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 099516b90c504205b894b387542221e8c0c98b40..83a5b68c785a88594e6e3824ed282844086f7f1a 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -4257,6 +4257,76 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* @return The local difficulty
*/
public float getLocalDifficultyAt(@NotNull Location location);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to all players on this world.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Clears all debug block highlights for all players on this world.
+ */
+ void clearBlockHighlights();
// Purpur end
/**
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 972cca3e02296f94099f965a4f7662ec63a067ea..ec49be86fa9b2612ae2853f06f503bffa3a1271d 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3834,5 +3834,75 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @deprecated Use {@link #resetIdleDuration()} instead
*/
void resetIdleTimer();
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param argb Color of the highlight. ARGB int. Will be ignored on some versions of vanilla client
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, int argb);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Creates debug block highlight on specified block location and show it to this player.
+ * <p>
+ * Clients may be inconsistent in displaying it.
+ * @param location Location to highlight
+ * @param duration Duration for highlight to show in milliseconds
+ * @param text Text to show above the highlight
+ * @param color Color of the highlight. Will be ignored on some versions of vanilla client
+ * @param transparency Transparency of the highlight
+ * @throws IllegalArgumentException If transparency is outside 0-255 range
+ */
+ void sendBlockHighlight(@NotNull Location location, int duration, @NotNull String text, @NotNull org.bukkit.Color color, int transparency);
+
+ /**
+ * Clears all debug block highlights
+ */
+ void clearBlockHighlights();
// Purpur end
}

View File

@@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Fri, 23 Sep 2022 18:35:28 -0700
Subject: [PATCH] Add death screen API
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index ec49be86fa9b2612ae2853f06f503bffa3a1271d..d057743b8f6a463434c1f76398c7a98614b19d47 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3904,5 +3904,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Clears all debug block highlights
*/
void clearBlockHighlights();
+
+ /**
+ * Sends a player the death screen with a specified death message.
+ *
+ * @param message The death message to show the player
+ */
+ void sendDeathScreen(@NotNull net.kyori.adventure.text.Component message);
+
+ /**
+ * Sends a player the death screen with a specified death message,
+ * along with the entity that caused the death.
+ *
+ * @param message The death message to show the player
+ * @param killer The entity that killed the player
+ * @deprecated Use {@link #sendDeathScreen(net.kyori.adventure.text.Component)} instead, as 1.20 removed the killer ID from the packet.
+ */
+ @Deprecated(since = "1.20")
+ default void sendDeathScreen(@NotNull net.kyori.adventure.text.Component message, @Nullable Entity killer) {
+ sendDeathScreen(message);
+ }
// Purpur end
}

View File

@@ -1,72 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 1 Oct 2022 17:08:23 -0700
Subject: [PATCH] Language API
diff --git a/src/main/java/org/purpurmc/purpur/language/Language.java b/src/main/java/org/purpurmc/purpur/language/Language.java
new file mode 100644
index 0000000000000000000000000000000000000000..38483d908ed830e97883733bee2370f87060f4c7
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/language/Language.java
@@ -0,0 +1,60 @@
+package org.purpurmc.purpur.language;
+
+import net.kyori.adventure.translation.Translatable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents a language that can translate translation keys
+ */
+public abstract class Language {
+ private static Language language;
+
+ /**
+ * Returns the default language of the server
+ */
+ @NotNull
+ public static Language getLanguage() {
+ return language;
+ }
+
+ public static void setLanguage(@NotNull Language language) {
+ if (Language.language != null) {
+ throw new UnsupportedOperationException("Cannot redefine singleton Language");
+ }
+ Language.language = language;
+ }
+
+ /**
+ * Checks if a certain translation key is translatable with this language
+ * @param key The translation key
+ * @return Whether this language can translate the key
+ */
+ abstract public boolean has(@NotNull String key);
+
+ /**
+ * Checks if a certain translation key is translatable with this language
+ * @param key The translation key
+ * @return Whether this language can translate the key
+ */
+ public boolean has(@NotNull Translatable key) {
+ return has(key.translationKey());
+ }
+
+ /**
+ * Translates a translation key to this language
+ * @param key The translation key
+ * @return The translated key, or the translation key if it couldn't be translated
+ */
+ @NotNull
+ abstract public String getOrDefault(@NotNull String key);
+
+ /**
+ * Translates a translation key to this language
+ * @param key The translation key
+ * @return The translated key, or the translation key if it couldn't be translated
+ */
+ @NotNull
+ public String getOrDefault(@NotNull Translatable key) {
+ return getOrDefault(key.translationKey());
+ }
+}

View File

@@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Krakenied <Krakenied1@gmail.com>
Date: Fri, 14 Oct 2022 23:11:27 +0200
Subject: [PATCH] Add log suppression for LibraryLoader
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..f1e58639213be0c43cd2ff090b625e7d0a67e8be 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -55,6 +55,7 @@ public final class JavaPluginLoader implements PluginLoader {
private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
private final List<PluginClassLoader> loaders = new CopyOnWriteArrayList<PluginClassLoader>();
private final LibraryLoader libraryLoader;
+ public static boolean SuppressLibraryLoaderLogger = false; // Purpur
/**
* This class was not meant to be constructed explicitly
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
index 8e1b6be2462aaa692efa1f72986921a6dc357196..b6e18b12fd4d61ce92203582906d24b4d14e6cc5 100644
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
@@ -68,6 +68,7 @@ public class LibraryLoader
@Override
public void transferStarted(@NotNull TransferEvent event) throws TransferCancelledException
{
+ if (!JavaPluginLoader.SuppressLibraryLoaderLogger) // Purpur
logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
}
} );
@@ -88,6 +89,7 @@ public class LibraryLoader
{
return null;
}
+ if (!JavaPluginLoader.SuppressLibraryLoaderLogger) // Purpur
logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
{
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), desc.getLibraries().size() // Paper - use configured log prefix
@@ -135,6 +137,7 @@ public class LibraryLoader
}
jarFiles.add( url );
+ if (!JavaPluginLoader.SuppressLibraryLoaderLogger) // Purpur
logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[]
{
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), file // Paper - use configured log prefix

View File

@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Racci <90304606+DaRacci@users.noreply.github.com>
Date: Fri, 4 Feb 2022 16:09:47 +1100
Subject: [PATCH] Fire Immunity API
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index f482467ae784b134da97eb38afb7f12585520297..07b8c0dd049ff783fd2e408be634642479bf8b1e 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -1192,5 +1192,18 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* @return True if in daylight
*/
boolean isInDaylight();
+
+ /**
+ * Checks if the entity is fire immune
+ *
+ * @return True if fire immune
+ */
+ boolean isImmuneToFire();
+
+ /**
+ * Sets if the entity is fire immune
+ * Set this to null to restore the entity type default
+ */
+ void setImmuneToFire(@Nullable Boolean fireImmune);
// Purpur end
}

View File

@@ -1,71 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Sat, 29 Oct 2022 00:06:05 +0200
Subject: [PATCH] Added goat ram event
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/GoatRamEntityEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/GoatRamEntityEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f62c14f3d4999e9112c1c73642aa337d97b94b5a
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/GoatRamEntityEvent.java
@@ -0,0 +1,59 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.entity.Goat;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a goat rams an entity
+ */
+public class GoatRamEntityEvent extends EntityEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity rammedEntity;
+ private boolean cancelled;
+
+ public GoatRamEntityEvent(@NotNull Goat goat, @NotNull LivingEntity rammedEntity) {
+ super(goat);
+ this.rammedEntity = rammedEntity;
+ }
+
+ /**
+ * Returns the entity that was rammed by the goat
+ *
+ * @return The rammed entity
+ */
+ @NotNull
+ public LivingEntity getRammedEntity() {
+ return this.rammedEntity;
+ }
+
+ @Override
+ @NotNull
+ public Goat getEntity() {
+ return (Goat) super.getEntity();
+ }
+
+ @Override
+ @NotNull
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+}

View File

@@ -1,135 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Mon, 26 Dec 2022 23:40:13 +0100
Subject: [PATCH] Add PreExplodeEvents
diff --git a/src/main/java/org/purpurmc/purpur/event/PreBlockExplodeEvent.java b/src/main/java/org/purpurmc/purpur/event/PreBlockExplodeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ea97ddceedb7c719e8a50a0dd8f3f0919ca1647
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/PreBlockExplodeEvent.java
@@ -0,0 +1,53 @@
+package org.purpurmc.purpur.event;
+
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.block.BlockExplodeEvent;
+import org.jetbrains.annotations.NotNull;
+import java.util.Collections;
+
+/**
+ * Called before a block's explosion is processed
+ */
+public class PreBlockExplodeEvent extends BlockExplodeEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled;
+ private final float yield;
+
+ public PreBlockExplodeEvent(@NotNull final Block what, final float yield, @NotNull BlockState explodedBlockState) {
+ super(what, explodedBlockState, Collections.emptyList(), yield);
+ this.yield = yield;
+ this.cancelled = false;
+ }
+
+ /**
+ * Returns the percentage of blocks to drop from this explosion
+ *
+ * @return The yield.
+ */
+ public float getYield() {
+ return yield;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/event/entity/PreEntityExplodeEvent.java b/src/main/java/org/purpurmc/purpur/event/entity/PreEntityExplodeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d4f68228861492baaea0bcc604dfef623b337ba
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/event/entity/PreEntityExplodeEvent.java
@@ -0,0 +1,64 @@
+package org.purpurmc.purpur.event.entity;
+
+import org.bukkit.Location;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.jetbrains.annotations.NotNull;
+import java.util.Collections;
+
+/**
+ * Called before an entity's explosion is processed
+ */
+public class PreEntityExplodeEvent extends EntityExplodeEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled;
+ private final float yield;
+ private final Location location;
+
+ public PreEntityExplodeEvent(@NotNull org.bukkit.entity.Entity what, @NotNull final Location location, final float yield) {
+ super(what, location, Collections.emptyList(), yield);
+ this.cancelled = false;
+ this.yield = yield;
+ this.location = location;
+ }
+
+ /**
+ * Returns the percentage of blocks to drop from this explosion
+ *
+ * @return The yield.
+ */
+ public float getYield() {
+ return yield;
+ }
+
+ /**
+ * Returns the location where the explosion happened.
+ *
+ * @return The location of the explosion
+ */
+ @NotNull
+ public Location getLocation() {
+ return location;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @Override
+ public @NotNull HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}

View File

@@ -1,93 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: EOT3000 <egor.tolstenkov@outlook.com>
Date: Sat, 10 Jun 2023 20:27:14 -0400
Subject: [PATCH] Stored Bee API
diff --git a/src/main/java/org/bukkit/block/EntityBlockStorage.java b/src/main/java/org/bukkit/block/EntityBlockStorage.java
index 739911cda33b373f99df627a3a378b37d7d461aa..51e78c22cd021722b963fe31d1d9175d141add1a 100644
--- a/src/main/java/org/bukkit/block/EntityBlockStorage.java
+++ b/src/main/java/org/bukkit/block/EntityBlockStorage.java
@@ -47,6 +47,24 @@ public interface EntityBlockStorage<T extends Entity> extends TileState {
@NotNull
List<T> releaseEntities();
+ // Purpur start
+ /**
+ * Releases a stored entity, and returns the entity in the world.
+ *
+ * @param entity Entity to release
+ * @return The entity which was released, or null if the stored entity is not in the hive
+ */
+ @org.jetbrains.annotations.Nullable
+ T releaseEntity(@NotNull org.purpurmc.purpur.entity.StoredEntity<T> entity);
+
+ /**
+ * Gets all the entities currently stored in the block.
+ *
+ * @return List of all entities which are stored in the block
+ */
+ @NotNull
+ List<org.purpurmc.purpur.entity.StoredEntity<T>> getEntities();
+ //Purpur end
/**
* Add an entity to the block.
*
diff --git a/src/main/java/org/purpurmc/purpur/entity/StoredEntity.java b/src/main/java/org/purpurmc/purpur/entity/StoredEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..29540d55532197d2381a52ea9222b5785d224ef8
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/entity/StoredEntity.java
@@ -0,0 +1,52 @@
+package org.purpurmc.purpur.entity;
+
+import org.bukkit.Nameable;
+import org.bukkit.block.EntityBlockStorage;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.persistence.PersistentDataHolder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents an entity stored in a block
+ *
+ * @see org.bukkit.block.EntityBlockStorage
+ */
+public interface StoredEntity<T extends Entity> extends PersistentDataHolder, Nameable {
+ /**
+ * Checks if this entity has been released yet
+ *
+ * @return if this entity has been released
+ */
+ boolean hasBeenReleased();
+
+ /**
+ * Releases the entity from its stored block
+ *
+ * @return the released entity, or null if unsuccessful (including if this entity has already been released)
+ */
+ @Nullable
+ T release();
+
+ /**
+ * Returns the block in which this entity is stored
+ *
+ * @return the EntityBlockStorage in which this entity is stored, or null if it has been released
+ */
+ @Nullable
+ EntityBlockStorage<T> getBlockStorage();
+
+ /**
+ * Gets the entity type of this stored entity
+ *
+ * @return the type of entity this stored entity represents
+ */
+ @NotNull
+ EntityType getType();
+
+ /**
+ * Writes data to the block entity snapshot. {@link EntityBlockStorage#update()} must be run in order to update the block in game.
+ */
+ void update();
+}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 5 Jul 2023 12:48:08 -0500
Subject: [PATCH] Explorer Map API
diff --git a/src/main/java/org/bukkit/map/MapRenderer.java b/src/main/java/org/bukkit/map/MapRenderer.java
index cb7040876a99a5a7e49b81684ef0f3b79584c376..22d8f31b1b8a5dbb5ab3275068642937c097abfe 100644
--- a/src/main/java/org/bukkit/map/MapRenderer.java
+++ b/src/main/java/org/bukkit/map/MapRenderer.java
@@ -54,4 +54,12 @@ public abstract class MapRenderer {
*/
public abstract void render(@NotNull MapView map, @NotNull MapCanvas canvas, @NotNull Player player);
+ // Purpur - start
+ /**
+ * Check if this is an explorer (aka treasure) map.
+ *
+ * @return True if explorer map
+ */
+ public abstract boolean isExplorerMap();
+ // Purpur - end
}

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <contact@granny.dev>
Date: Sun, 11 Feb 2024 23:07:47 -0800
Subject: [PATCH] Stonecutter damage
diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java b/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
index 446b3ffd5caca5344be1c250475679834cd0d4a2..3da8d3d8925cd7a111c0c357bceecfd3a801c8eb 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDamageEvent.java
@@ -303,7 +303,8 @@ public class EntityDamageEvent extends EntityEvent implements Cancellable {
WORLD_BORDER,
/**
* Damage caused when an entity contacts a block such as a Cactus,
- * Dripstone (Stalagmite) or Berry Bush.
+ * Dripstone (Stalagmite) or Berry Bush. (Stonecutters too if you
+ * have the Stonecutter damage Purpur feature enabled)
* <p>
* Damage: variable
*/

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 4 May 2019 00:57:16 -0500
Subject: [PATCH] Ridables
diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index 069f2668f5229b0368b796e65eef1648fba0a097..50dc058cd8ecade74be30c75907d07f349c4df87 100644
--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -442,6 +442,12 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Zombie> ZOMBIE_ATTACK_TURTLE_EGG = create("zombie_attack_turtle_egg", Zombie.class);
+ // Purpur start
+ GoalKey<Mob> MOB_HAS_RIDER = GoalKey.of(Mob.class, NamespacedKey.minecraft("has_rider"));
+ GoalKey<AbstractHorse> HORSE_HAS_RIDER = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("horse_has_rider"));
+ GoalKey<Llama> LLAMA_HAS_RIDER = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_has_rider"));
+ // Purpur end
+
/**
* Removed in 1.20.2
*/

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 28 Jun 2020 21:50:55 -0500
Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms
diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index 50dc058cd8ecade74be30c75907d07f349c4df87..b3a1325786fffb1a585b3911c75c03d184e8a848 100644
--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -446,6 +446,8 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Mob> MOB_HAS_RIDER = GoalKey.of(Mob.class, NamespacedKey.minecraft("has_rider"));
GoalKey<AbstractHorse> HORSE_HAS_RIDER = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("horse_has_rider"));
GoalKey<Llama> LLAMA_HAS_RIDER = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_has_rider"));
+ GoalKey<Phantom> FIND_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("find_crystal"));
+ GoalKey<Phantom> ORBIT_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal"));
// Purpur end
/**

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: nitricspace <nitricspace@users.noreply.github.com>
Date: Wed, 23 Sep 2020 22:14:38 +0100
Subject: [PATCH] Add option to disable zombie aggressiveness towards villagers
when lagging
diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index b3a1325786fffb1a585b3911c75c03d184e8a848..31c4d5da936f88e68c67c6e464b94563a47a0f34 100644
--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -448,6 +448,8 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Llama> LLAMA_HAS_RIDER = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_has_rider"));
GoalKey<Phantom> FIND_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("find_crystal"));
GoalKey<Phantom> ORBIT_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal"));
+ GoalKey<Drowned> DROWNED_ATTACK_VILLAGER = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack_villager"));
+ GoalKey<Zombie> ZOMBIE_ATTACK_VILLAGER = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_villager"));
// Purpur end
/**

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Tue, 8 Dec 2020 17:15:15 -0500
Subject: [PATCH] Rabid Wolf API
diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index 31c4d5da936f88e68c67c6e464b94563a47a0f34..a41aa6c187d60373630eb803cb69d58b85eacc98 100644
--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -450,6 +450,7 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Phantom> ORBIT_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal"));
GoalKey<Drowned> DROWNED_ATTACK_VILLAGER = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack_villager"));
GoalKey<Zombie> ZOMBIE_ATTACK_VILLAGER = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_villager"));
+ GoalKey<Wolf> AVOID_RABID_WOLF = GoalKey.of(Wolf.class, NamespacedKey.minecraft("avoid_rabid_wolf"));
// Purpur end
/**

View File

@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 13 May 2021 21:38:01 -0500
Subject: [PATCH] Iron golem poppy calms anger
diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index a41aa6c187d60373630eb803cb69d58b85eacc98..9b991201a2f6cc9feccccf7f4e7bcded64117764 100644
--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -451,6 +451,7 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
GoalKey<Drowned> DROWNED_ATTACK_VILLAGER = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack_villager"));
GoalKey<Zombie> ZOMBIE_ATTACK_VILLAGER = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_villager"));
GoalKey<Wolf> AVOID_RABID_WOLF = GoalKey.of(Wolf.class, NamespacedKey.minecraft("avoid_rabid_wolf"));
+ GoalKey<IronGolem> RECEIVE_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("receive_flower"));
// Purpur end
/**

View File

@@ -1,529 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 9 May 2019 18:09:43 -0500
Subject: [PATCH] Purpur config files
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
index 4b002e8b75d117b726b0de274a76d3596fce015b..8cde30544e14f8fc2dac32966ae3c21f8cf3a551 100644
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
@@ -593,7 +593,7 @@ public class Metrics {
boolean logFailedRequests = config.getBoolean("logFailedRequests", false);
// Only start Metrics, if it's enabled in the config
if (config.getBoolean("enabled", true)) {
- Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger());
+ Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish // Purpur
metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> {
String minecraftVersion = Bukkit.getVersion();
@@ -602,16 +602,8 @@ public class Metrics {
}));
metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size()));
- metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline"));
- final String paperVersion;
- final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion();
- if (implVersion != null) {
- final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1);
- paperVersion = "git-Paper-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash);
- } else {
- paperVersion = "unknown";
- }
- metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> paperVersion));
+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() ? "bungee" : "offline"))); // Purpur
+ metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() != null) ? org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() : "unknown")); // Purpur
metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> {
Map<String, Map<String, Integer>> map = new HashMap<>();
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
index e6c7f62ed379a78645933670299e4fcda8540ed1..edb94e5601acc38994dac20a167b145de778d426 100644
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
@@ -331,6 +331,30 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
}
}
+ // 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(Supplier<Component> feedbackSupplier, boolean broadcastToOps) {
boolean flag1 = this.source.acceptsSuccess() && !this.silent;
boolean flag2 = broadcastToOps && this.source.shouldInformAdmins() && !this.silent;
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index eb4fc900164d1fb3a78653ae8bc42ea30323f5b7..6d47aa73788eef78aa6714384db879b4e907de9b 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -232,6 +232,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
thread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
+ // Purpur start
+ try {
+ org.purpurmc.purpur.PurpurConfig.init((java.io.File) options.valueOf("purpur-settings"));
+ } catch (Exception e) {
+ DedicatedServer.LOGGER.error("Unable to load server configuration", e);
+ return false;
+ }
+ org.purpurmc.purpur.PurpurConfig.registerCommands();
+ // Purpur end
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index b4ef3ad2c17168085372f1fe46809f02d9dfe74a..04f7f6743aabdca54892b2b155386f86032cf807 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -170,6 +170,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper end - add paper world config
public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
+ public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
public static BlockPos lastPhysicsProblem; // Spigot
private org.spigotmc.TickLimiter entityLimiter;
@@ -216,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
+ this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur
this.generator = gen;
this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 467ef4ffd6ee13b247ac9e453b006ec3d89362c9..d97f33d654086c892f01e47a59be7e37f6e03ae7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1054,6 +1054,7 @@ public final class CraftServer implements Server {
org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot
this.console.paperConfigurations.reloadConfigs(this.console);
+ org.purpurmc.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur
for (ServerLevel world : this.console.getAllLevels()) {
// world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty
world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean))
@@ -1069,6 +1070,7 @@ public final class CraftServer implements Server {
}
}
world.spigotConfig.init(); // Spigot
+ world.purpurConfig.init(); // Purpur
}
Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper
@@ -1084,6 +1086,7 @@ public final class CraftServer implements Server {
this.reloadData();
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
+ org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
@@ -3048,6 +3051,18 @@ public final class CraftServer implements Server {
return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console);
}
+ // Purpur start
+ @Override
+ public YamlConfiguration getPurpurConfig() {
+ return org.purpurmc.purpur.PurpurConfig.config;
+ }
+
+ @Override
+ public java.util.Properties getServerProperties() {
+ return getProperties().properties;
+ }
+ // Purpur end
+
@Override
public void restart() {
org.spigotmc.RestartCommand.restart();
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index c988afa496d25314451435eedd64079a0d87cef0..45a33086e1bb8a70e0fa01090731d27a0474da41 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -175,6 +175,14 @@ public class Main {
.describedAs("Jar file");
// Paper end
+ // Purpur Start
+ acceptsAll(asList("purpur", "purpur-settings"), "File for purpur settings")
+ .withRequiredArg()
+ .ofType(File.class)
+ .defaultsTo(new File("purpur.yml"))
+ .describedAs("Yml file");
+ // Purpur end
+
// Paper start
acceptsAll(asList("server-name"), "Name of the server")
.withRequiredArg()
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f015144be0a7a448c6c2b0765232c02ad405d09
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -0,0 +1,175 @@
+package org.purpurmc.purpur;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMap;
+import com.mojang.datafixers.util.Pair;
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.effect.MobEffect;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.entity.EntityDimensions;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.food.FoodProperties;
+import net.minecraft.world.food.Foods;
+import net.minecraft.world.item.enchantment.Enchantment;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.purpurmc.purpur.command.PurpurCommand;
+import org.purpurmc.purpur.task.TPSBarTask;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+
+@SuppressWarnings("unused")
+public class PurpurConfig {
+ private static final String HEADER = "This is the main configuration file for Purpur.\n"
+ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n"
+ + "with caution, and make sure you know what each option does before configuring.\n"
+ + "\n"
+ + "If you need help with the configuration or have any questions related to Purpur,\n"
+ + "join us in our Discord guild.\n"
+ + "\n"
+ + "Website: https://purpurmc.org \n"
+ + "Docs: https://purpurmc.org/docs \n";
+ private static File CONFIG_FILE;
+ public static YamlConfiguration config;
+
+ private static Map<String, Command> commands;
+
+ public static int version;
+ static boolean verbose;
+
+ public static void init(File configFile) {
+ CONFIG_FILE = configFile;
+ config = new YamlConfiguration();
+ try {
+ config.load(CONFIG_FILE);
+ } catch (IOException ignore) {
+ } catch (InvalidConfigurationException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Could not load purpur.yml, please correct your syntax errors", ex);
+ throw Throwables.propagate(ex);
+ }
+ config.options().header(HEADER);
+ config.options().copyDefaults(true);
+ verbose = getBoolean("verbose", false);
+
+ commands = new HashMap<>();
+ commands.put("purpur", new PurpurCommand("purpur"));
+
+ version = getInt("config-version", 35);
+ set("config-version", 35);
+
+ readConfig(PurpurConfig.class, null);
+
+ Blocks.rebuildCache();
+ }
+
+ protected static void log(String s) {
+ if (verbose) {
+ log(Level.INFO, s);
+ }
+ }
+
+ protected static void log(Level level, String s) {
+ Bukkit.getLogger().log(level, s);
+ }
+
+ public static void registerCommands() {
+ for (Map.Entry<String, Command> entry : commands.entrySet()) {
+ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Purpur", entry.getValue());
+ }
+ }
+
+ static void readConfig(Class<?> clazz, Object instance) {
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (Modifier.isPrivate(method.getModifiers())) {
+ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
+ try {
+ method.setAccessible(true);
+ method.invoke(instance);
+ } catch (InvocationTargetException ex) {
+ throw Throwables.propagate(ex.getCause());
+ } catch (Exception ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex);
+ }
+ }
+ }
+ }
+
+ try {
+ config.save(CONFIG_FILE);
+ } catch (IOException ex) {
+ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex);
+ }
+ }
+
+ private static void set(String path, Object val) {
+ config.addDefault(path, val);
+ config.set(path, val);
+ }
+
+ private static String getString(String path, String def) {
+ config.addDefault(path, def);
+ return config.getString(path, config.getString(path));
+ }
+
+ private static boolean getBoolean(String path, boolean def) {
+ config.addDefault(path, def);
+ return config.getBoolean(path, config.getBoolean(path));
+ }
+
+ private static double getDouble(String path, double def) {
+ config.addDefault(path, def);
+ return config.getDouble(path, config.getDouble(path));
+ }
+
+ private static int getInt(String path, int def) {
+ config.addDefault(path, def);
+ return config.getInt(path, config.getInt(path));
+ }
+
+ private static <T> List<?> getList(String path, T def) {
+ config.addDefault(path, def);
+ return config.getList(path, config.getList(path));
+ }
+
+ static Map<String, Object> getMap(String path, Map<String, Object> def) {
+ if (def != null && config.getConfigurationSection(path) == null) {
+ config.addDefault(path, def);
+ return def;
+ }
+ return toMap(config.getConfigurationSection(path));
+ }
+
+ private static Map<String, Object> toMap(ConfigurationSection section) {
+ ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
+ if (section != null) {
+ for (String key : section.getKeys(false)) {
+ Object obj = section.get(key);
+ if (obj != null) {
+ builder.put(key, obj instanceof ConfigurationSection val ? toMap(val) : obj);
+ }
+ }
+ }
+ return builder.build();
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f0732c2b8f85185b6dfc1db3119c22e8be7f5da
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -0,0 +1,92 @@
+package org.purpurmc.purpur;
+
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.item.DyeColor;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.state.properties.Tilt;
+import org.purpurmc.purpur.tool.Flattenable;
+import org.purpurmc.purpur.tool.Strippable;
+import org.purpurmc.purpur.tool.Tillable;
+import org.purpurmc.purpur.tool.Waxable;
+import org.purpurmc.purpur.tool.Weatherable;
+import org.apache.commons.lang.BooleanUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.World;
+import org.bukkit.configuration.ConfigurationSection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.logging.Level;
+import static org.purpurmc.purpur.PurpurConfig.log;
+
+@SuppressWarnings("unused")
+public class PurpurWorldConfig {
+
+ private final String worldName;
+ private final World.Environment environment;
+
+ public PurpurWorldConfig(String worldName, World.Environment environment) {
+ this.worldName = worldName;
+ this.environment = environment;
+ init();
+ }
+
+ public void init() {
+ log("-------- World Settings For [" + worldName + "] --------");
+ PurpurConfig.readConfig(PurpurWorldConfig.class, this);
+ }
+
+ private void set(String path, Object val) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, val);
+ PurpurConfig.config.set("world-settings.default." + path, val);
+ if (PurpurConfig.config.get("world-settings." + worldName + "." + path) != null) {
+ PurpurConfig.config.addDefault("world-settings." + worldName + "." + path, val);
+ PurpurConfig.config.set("world-settings." + worldName + "." + path, val);
+ }
+ }
+
+ private ConfigurationSection getConfigurationSection(String path) {
+ ConfigurationSection section = PurpurConfig.config.getConfigurationSection("world-settings." + worldName + "." + path);
+ return section != null ? section : PurpurConfig.config.getConfigurationSection("world-settings.default." + path);
+ }
+
+ private String getString(String path, String def) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, def);
+ return PurpurConfig.config.getString("world-settings." + worldName + "." + path, PurpurConfig.config.getString("world-settings.default." + path));
+ }
+
+ private boolean getBoolean(String path, boolean def) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, def);
+ return PurpurConfig.config.getBoolean("world-settings." + worldName + "." + path, PurpurConfig.config.getBoolean("world-settings.default." + path));
+ }
+
+ private double getDouble(String path, double def) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, def);
+ return PurpurConfig.config.getDouble("world-settings." + worldName + "." + path, PurpurConfig.config.getDouble("world-settings.default." + path));
+ }
+
+ private int getInt(String path, int def) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, def);
+ return PurpurConfig.config.getInt("world-settings." + worldName + "." + path, PurpurConfig.config.getInt("world-settings.default." + path));
+ }
+
+ private <T> List<?> getList(String path, T def) {
+ PurpurConfig.config.addDefault("world-settings.default." + path, def);
+ return PurpurConfig.config.getList("world-settings." + worldName + "." + path, PurpurConfig.config.getList("world-settings.default." + path));
+ }
+
+ private Map<String, Object> getMap(String path, Map<String, Object> def) {
+ final Map<String, Object> fallback = PurpurConfig.getMap("world-settings.default." + path, def);
+ final Map<String, Object> value = PurpurConfig.getMap("world-settings." + worldName + "." + path, null);
+ return value.isEmpty() ? fallback : value;
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/command/PurpurCommand.java b/src/main/java/org/purpurmc/purpur/command/PurpurCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..afdf04f8b22ad0b7c0b41675e44687b49c2f86d6
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/command/PurpurCommand.java
@@ -0,0 +1,65 @@
+package org.purpurmc.purpur.command;
+
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import org.purpurmc.purpur.PurpurConfig;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class PurpurCommand extends Command {
+ public PurpurCommand(String name) {
+ super(name);
+ this.description = "Purpur related commands";
+ this.usageMessage = "/purpur [reload | version]";
+ this.setPermission("bukkit.command.purpur");
+ }
+
+ @Override
+ public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
+ if (args.length == 1) {
+ return Stream.of("reload", "version")
+ .filter(arg -> arg.startsWith(args[0].toLowerCase()))
+ .collect(Collectors.toList());
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+ if (!testPermission(sender)) return true;
+
+ if (args.length != 1) {
+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
+ return false;
+ }
+
+ if (args[0].equalsIgnoreCase("reload")) {
+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues.");
+ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server.");
+
+ MinecraftServer console = MinecraftServer.getServer();
+ PurpurConfig.init((File) console.options.valueOf("purpur-settings"));
+ for (ServerLevel level : console.getAllLevels()) {
+ level.purpurConfig.init();
+ }
+ console.server.reloadCount++;
+
+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Purpur config reload complete.");
+ } else if (args[0].equalsIgnoreCase("version")) {
+ Command verCmd = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version");
+ if (verCmd != null) {
+ return verCmd.execute(sender, commandLabel, new String[0]);
+ }
+ }
+
+ return true;
+ }
+}

View File

@@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 30 Jul 2021 14:31:25 -0500
Subject: [PATCH] Purpur client support
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 8437316888c6056060a2780652147590b6fe7443..8b07eb1c428bc70b8ee07ea2209f1898d6034809 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -298,6 +298,7 @@ public class ServerPlayer extends Player {
public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
public @Nullable String clientBrandName = null; // Paper - Brand support
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
+ public boolean purpurClient = false; // Purpur
// Paper start - replace player chunk loader
private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 8ac5d8ccf731100a1be690cb2ed1be82cadba8ed..4228fd441f8350d43bd545e31c920304f07968bc 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -78,6 +78,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
public final java.util.Map<java.util.UUID, net.kyori.adventure.resource.ResourcePackCallback> packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
protected static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support
+ protected static final ResourceLocation PURPUR_CLIENT = new ResourceLocation("purpur", "client"); // Purpur
public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit
this.server = minecraftserver;
@@ -170,6 +171,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex);
this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
}
+ // Purpur start
+ } else if (identifier.equals(PURPUR_CLIENT)) {
+ try {
+ player.purpurClient = true;
+ } catch (Exception ignore) {
+ }
+ // Purpur end
} else if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER)) {
try {
String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 5f896948d158651cd9837364759dbfbcce6b7d21..7f78db4e0331d0f4801807ed1242642ee940d0f8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3522,4 +3522,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void setSendViewDistance(final int viewDistance) {
this.getHandle().setSendViewDistance(viewDistance);
}
+
+ // Purpur start
+ @Override
+ public boolean usesPurpurClient() {
+ return getHandle().purpurClient;
+ }
+ // Purpur end
}

View File

@@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sun, 12 Jun 2022 06:20:21 -0500
Subject: [PATCH] Fix decompile errors
diff --git a/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java b/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
index b0d26b0eadb2a43924629424a6c13198aace8f69..9f5c3ec2eae9b30bdb8dbcb328d7f701cb7aeb9d 100644
--- a/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
+++ b/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
@@ -52,7 +52,7 @@ public class BuildContexts<T extends ExecutionCommandSource<T>> {
}
RedirectModifier<T> redirectModifier = commandContext.getRedirectModifier();
- if (redirectModifier instanceof CustomModifierExecutor<T> customModifierExecutor) {
+ if (redirectModifier instanceof CustomModifierExecutor customModifierExecutor) { // Purpur - decompile error
customModifierExecutor.apply(baseSource, list, contextChain, chainModifiers, ExecutionControl.create(context, frame));
return;
}
@@ -92,11 +92,11 @@ public class BuildContexts<T extends ExecutionCommandSource<T>> {
if (list.isEmpty()) {
if (chainModifiers.isReturn()) {
- context.queueNext(new CommandQueueEntry<>(frame, FallthroughTask.instance()));
+ context.queueNext(new CommandQueueEntry<>(frame, (EntryAction<T>) FallthroughTask.instance())); // Purpur - decompile error
}
} else {
CommandContext<T> commandContext2 = contextChain.getTopContext();
- if (commandContext2.getCommand() instanceof CustomCommandExecutor<T> customCommandExecutor) {
+ if (commandContext2.getCommand() instanceof CustomCommandExecutor customCommandExecutor) { // Purpur - decompile error
ExecutionControl<T> executionControl = ExecutionControl.create(context, frame);
for (T executionCommandSource2 : list) {
diff --git a/src/main/java/net/minecraft/commands/synchronization/ArgumentTypeInfos.java b/src/main/java/net/minecraft/commands/synchronization/ArgumentTypeInfos.java
index 7b118a92a6eb779f800ae8f5d8f6e3c861fc4f6a..057a038e8dcacd7496a0b2373de2c20255a5c297 100644
--- a/src/main/java/net/minecraft/commands/synchronization/ArgumentTypeInfos.java
+++ b/src/main/java/net/minecraft/commands/synchronization/ArgumentTypeInfos.java
@@ -119,10 +119,10 @@ public class ArgumentTypeInfos {
register(registry, "dimension", DimensionArgument.class, SingletonArgumentInfo.contextFree(DimensionArgument::dimension));
register(registry, "gamemode", GameModeArgument.class, SingletonArgumentInfo.contextFree(GameModeArgument::gameMode));
register(registry, "time", TimeArgument.class, new TimeArgument.Info());
- register(registry, "resource_or_tag", fixClassType(ResourceOrTagArgument.class), new ResourceOrTagArgument.Info());
- register(registry, "resource_or_tag_key", fixClassType(ResourceOrTagKeyArgument.class), new ResourceOrTagKeyArgument.Info());
- register(registry, "resource", fixClassType(ResourceArgument.class), new ResourceArgument.Info());
- register(registry, "resource_key", fixClassType(ResourceKeyArgument.class), new ResourceKeyArgument.Info());
+ register(registry, "resource_or_tag", fixClassType(ResourceOrTagArgument.class), new ResourceOrTagArgument.Info<>()); // Purpur - decompile error
+ register(registry, "resource_or_tag_key", fixClassType(ResourceOrTagKeyArgument.class), new ResourceOrTagKeyArgument.Info<>()); // Purpur - decompile error
+ register(registry, "resource", fixClassType(ResourceArgument.class), new ResourceArgument.Info<>()); // Purpur - decompile error
+ register(registry, "resource_key", fixClassType(ResourceKeyArgument.class), new ResourceKeyArgument.Info<>()); // Purpur - decompile error
register(registry, "template_mirror", TemplateMirrorArgument.class, SingletonArgumentInfo.contextFree(TemplateMirrorArgument::templateMirror));
register(registry, "template_rotation", TemplateRotationArgument.class, SingletonArgumentInfo.contextFree(TemplateRotationArgument::templateRotation));
register(registry, "heightmap", HeightmapTypeArgument.class, SingletonArgumentInfo.contextFree(HeightmapTypeArgument::heightmap));

View File

@@ -1,107 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Tue, 29 Jun 2021 21:37:40 -0500
Subject: [PATCH] Component related conveniences
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 8b07eb1c428bc70b8ee07ea2209f1898d6034809..0b9c85adaf5c7b5dcb23ab74a4fd02e6c0798851 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1978,6 +1978,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 a2142930b4d4b05987c90496fb9d733d99040aa0..2d6b6795703431939005aa09d1ed590c3f755163 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1063,6 +1063,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 160dc3216e8f5db5f9b3cce5e2d655f2b35b208a..43b9a7e8ed9043c4d3f8295258a27209ddb4474b 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -177,6 +177,15 @@ public class DamageSource {
}
}
+ // 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 String getMsgId() {
return this.type().msgId();
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 2bc85351e6e52f90da5fdb29d8d042a06132d742..6c7f80723d67baf0ca036e0a12c3007144352edf 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -4190,6 +4190,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
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) {}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,298 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 23 May 2019 21:50:37 -0500
Subject: [PATCH] Barrels and enderchests 6 rows
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 2d6b6795703431939005aa09d1ed590c3f755163..f10dcc0debcdd2077ee53cb1aefca8abd12f3ecd 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1188,6 +1188,27 @@ public abstract class PlayerList {
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
} // Paper - Add sendOpLevel API
+
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.enderChestSixRows && org.purpurmc.purpur.PurpurConfig.enderChestPermissionRows) {
+ org.bukkit.craftbukkit.entity.CraftHumanEntity bukkit = player.getBukkitEntity();
+ if (bukkit.hasPermission("purpur.enderchest.rows.six")) {
+ player.sixRowEnderchestSlotCount = 54;
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.five")) {
+ player.sixRowEnderchestSlotCount = 45;
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.four")) {
+ player.sixRowEnderchestSlotCount = 36;
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.three")) {
+ player.sixRowEnderchestSlotCount = 27;
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.two")) {
+ player.sixRowEnderchestSlotCount = 18;
+ } else if (bukkit.hasPermission("purpur.enderchest.rows.one")) {
+ player.sixRowEnderchestSlotCount = 9;
+ }
+ } else {
+ player.sixRowEnderchestSlotCount = -1;
+ }
+ //Purpur end
}
public boolean isWhiteListed(GameProfile profile) {
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 90e44c7281935bc7ceb3b220bbcd73187fed44fb..0641e448e0e98694976b820c2e9c4868f2b76909 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -195,6 +195,7 @@ public abstract class Player extends LivingEntity {
public boolean ignoreFallDamageFromCurrentImpulse;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
+ public int sixRowEnderchestSlotCount = -1; // Purpur
// CraftBukkit start
public boolean fauxSleeping;
diff --git a/src/main/java/net/minecraft/world/inventory/ChestMenu.java b/src/main/java/net/minecraft/world/inventory/ChestMenu.java
index 0dbfd23bbfc6ad203f048142f8c90ef741849fe1..9a80427d2bb470b6b1638e59aba57216676dcbd2 100644
--- a/src/main/java/net/minecraft/world/inventory/ChestMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/ChestMenu.java
@@ -67,10 +67,30 @@ public class ChestMenu extends AbstractContainerMenu {
return new ChestMenu(MenuType.GENERIC_9x6, syncId, playerInventory, 6);
}
+ // Purpur start
+ public static ChestMenu oneRow(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x1, syncId, playerInventory, inventory, 1);
+ }
+
+ public static ChestMenu twoRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x2, syncId, playerInventory, inventory, 2);
+ }
+ // Purpur end
+
public static ChestMenu threeRows(int syncId, Inventory playerInventory, Container inventory) {
return new ChestMenu(MenuType.GENERIC_9x3, syncId, playerInventory, inventory, 3);
}
+ // Purpur start
+ public static ChestMenu fourRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x4, syncId, playerInventory, inventory, 4);
+ }
+
+ public static ChestMenu fiveRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x5, syncId, playerInventory, inventory, 5);
+ }
+ // Purpur end
+
public static ChestMenu sixRows(int syncId, Inventory playerInventory, Container inventory) {
return new ChestMenu(MenuType.GENERIC_9x6, syncId, playerInventory, inventory, 6);
}
diff --git a/src/main/java/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/src/main/java/net/minecraft/world/inventory/PlayerEnderChestContainer.java
index a15d5ff872dbd77f3c3145e0328f3d02e431ff8c..1dcf36d502990d32fc4cd3ea69c3ea334baed69a 100644
--- a/src/main/java/net/minecraft/world/inventory/PlayerEnderChestContainer.java
+++ b/src/main/java/net/minecraft/world/inventory/PlayerEnderChestContainer.java
@@ -31,11 +31,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
}
public PlayerEnderChestContainer(Player owner) {
- super(27);
+ super(org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? 54 : 27); // Purpur
this.owner = owner;
// CraftBukkit end
}
+ // Purpur start
+ @Override
+ public int getContainerSize() {
+ return owner.sixRowEnderchestSlotCount < 0 ? super.getContainerSize() : owner.sixRowEnderchestSlotCount;
+ }
+ // Purpur end
+
public void setActiveChest(EnderChestBlockEntity blockEntity) {
this.activeChest = blockEntity;
}
diff --git a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
index 5f9858ef8d0ec1a74d469ab4426eb1db068873fd..d7ef772444b301d0a3f167679027195e4150b064 100644
--- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
@@ -91,7 +91,7 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
EnderChestBlockEntity enderChestBlockEntity = (EnderChestBlockEntity)blockEntity;
playerEnderChestContainer.setActiveChest(enderChestBlockEntity);
player.openMenu(
- new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE)
+ new SimpleMenuProvider((i, inventory, playerx) -> org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? getEnderChestSixRows(i, inventory, player, playerEnderChestContainer) : ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE) // Purpur
);
player.awardStat(Stats.OPEN_ENDERCHEST);
PiglinAi.angerNearbyPiglins(player, true);
@@ -102,6 +102,35 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
}
}
+ // Purpur start
+ private ChestMenu getEnderChestSixRows(int syncId, net.minecraft.world.entity.player.Inventory inventory, Player player, PlayerEnderChestContainer playerEnderChestContainer) {
+ if (org.purpurmc.purpur.PurpurConfig.enderChestPermissionRows) {
+ org.bukkit.craftbukkit.entity.CraftHumanEntity bukkitPlayer = player.getBukkitEntity();
+ if (bukkitPlayer.hasPermission("purpur.enderchest.rows.six")) {
+ player.sixRowEnderchestSlotCount = 54;
+ return ChestMenu.sixRows(syncId, inventory, playerEnderChestContainer);
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.five")) {
+ player.sixRowEnderchestSlotCount = 45;
+ return ChestMenu.fiveRows(syncId, inventory, playerEnderChestContainer);
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.four")) {
+ player.sixRowEnderchestSlotCount = 36;
+ return ChestMenu.fourRows(syncId, inventory, playerEnderChestContainer);
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.three")) {
+ player.sixRowEnderchestSlotCount = 27;
+ return ChestMenu.threeRows(syncId, inventory, playerEnderChestContainer);
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.two")) {
+ player.sixRowEnderchestSlotCount = 18;
+ return ChestMenu.twoRows(syncId, inventory, playerEnderChestContainer);
+ } else if (bukkitPlayer.hasPermission("purpur.enderchest.rows.one")) {
+ player.sixRowEnderchestSlotCount = 9;
+ return ChestMenu.oneRow(syncId, inventory, playerEnderChestContainer);
+ }
+ }
+ player.sixRowEnderchestSlotCount = -1;
+ return ChestMenu.sixRows(syncId, inventory, playerEnderChestContainer);
+ }
+ // Purpur end
+
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new EnderChestBlockEntity(pos, state);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
index 6186e55014bbb9d5bedaa0e9d196879c55339d42..f4f11292d6d00f4a7c65e3e2a157bba595f70889 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -68,7 +68,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
public BarrelBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.BARREL, pos, state);
- this.items = NonNullList.withSize(27, ItemStack.EMPTY);
+ // Purpur start
+ this.items = NonNullList.withSize(switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
+ case 2 -> 18;
+ case 1 -> 9;
+ default -> 27;
+ }, ItemStack.EMPTY);
+ // Purpur end
this.openersCounter = new ContainerOpenersCounter() {
@Override
protected void onOpen(Level world, BlockPos pos, BlockState state) {
@@ -119,7 +128,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
@Override
public int getContainerSize() {
- return 27;
+ // Purpur start
+ return switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
+ case 2 -> 18;
+ case 1 -> 9;
+ default -> 27;
+ };
+ // Purpur end
}
@Override
@@ -139,7 +157,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
@Override
protected AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) {
- return ChestMenu.threeRows(syncId, playerInventory, this);
+ // Purpur start
+ return switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
+ case 6 -> ChestMenu.sixRows(syncId, playerInventory, this);
+ case 5 -> ChestMenu.fiveRows(syncId, playerInventory, this);
+ case 4 -> ChestMenu.fourRows(syncId, playerInventory, this);
+ case 2 -> ChestMenu.twoRows(syncId, playerInventory, this);
+ case 1 -> ChestMenu.oneRow(syncId, playerInventory, this);
+ default -> ChestMenu.threeRows(syncId, playerInventory, this);
+ };
+ // Purpur end
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
index 977b77547f7ba62cef3640cf8d4f1c8e7cded53a..beae43e9b6fe447e7515d878ac175f461968768a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
@@ -184,8 +184,19 @@ public class CraftContainer extends AbstractContainerMenu {
case PLAYER:
case CHEST:
case ENDER_CHEST:
+ // Purpur start
+ this.delegate = new ChestMenu(org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? MenuType.GENERIC_9x6 : MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
+ break;
case BARREL:
- this.delegate = new ChestMenu(MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
+ this.delegate = new ChestMenu(switch (org.purpurmc.purpur.PurpurConfig.barrelRows) {
+ case 6 -> MenuType.GENERIC_9x6;
+ case 5 -> MenuType.GENERIC_9x5;
+ case 4 -> MenuType.GENERIC_9x4;
+ case 2 -> MenuType.GENERIC_9x2;
+ case 1 -> MenuType.GENERIC_9x1;
+ default -> MenuType.GENERIC_9x3;
+ }, windowId, bottom, top, top.getContainerSize() / 9);
+ // Purpur end
break;
case DISPENSER:
case DROPPER:
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
index af1ae3dacb628da23f7d2988c6e76d3fb2d64103..4ee2d501f882279b48edb4b8bf0824587c276bf6 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
@@ -84,7 +84,7 @@ public class CraftInventory implements Inventory {
@Override
public void setContents(ItemStack[] items) {
- Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize());
+ // Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize()); // Purpur
for (int i = 0; i < this.getSize(); i++) {
if (i >= items.length) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 463af65182c0894a75a138df8100f3f616143f4c..a0eb18409f72afe393581e6dc8e2260b3a25197f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -177,4 +177,39 @@ public class PurpurConfig {
private static void messages() {
cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob);
}
+
+ public static int barrelRows = 3;
+ public static boolean enderChestSixRows = false;
+ public static boolean enderChestPermissionRows = false;
+ private static void blockSettings() {
+ if (version < 3) {
+ boolean oldValue = getBoolean("settings.barrel.packed-barrels", true);
+ set("settings.blocks.barrel.six-rows", oldValue);
+ set("settings.packed-barrels", null);
+ oldValue = getBoolean("settings.large-ender-chests", true);
+ set("settings.blocks.ender_chest.six-rows", oldValue);
+ set("settings.large-ender-chests", null);
+ }
+ if (version < 20) {
+ boolean oldValue = getBoolean("settings.blocks.barrel.six-rows", false);
+ set("settings.blocks.barrel.rows", oldValue ? 6 : 3);
+ set("settings.blocks.barrel.six-rows", null);
+ }
+ barrelRows = getInt("settings.blocks.barrel.rows", barrelRows);
+ if (barrelRows < 1 || barrelRows > 6) {
+ Bukkit.getLogger().severe("settings.blocks.barrel.rows must be 1-6, resetting to default");
+ barrelRows = 3;
+ }
+ org.bukkit.event.inventory.InventoryType.BARREL.setDefaultSize(switch (barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
+ case 2 -> 18;
+ case 1 -> 9;
+ default -> 27;
+ });
+ enderChestSixRows = getBoolean("settings.blocks.ender_chest.six-rows", enderChestSixRows);
+ org.bukkit.event.inventory.InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27);
+ enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows);
+ }
}

View File

@@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 18 Oct 2019 22:50:12 -0500
Subject: [PATCH] Llama API
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java
index df695b444fa2a993d381e2f197182c3e91a68502..eb0faf58fa1a408f294fc62120b140def97f998d 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/LlamaFollowCaravanGoal.java
@@ -22,6 +22,7 @@ public class LlamaFollowCaravanGoal extends Goal {
@Override
public boolean canUse() {
+ if (!this.llama.shouldJoinCaravan) return false; // Purpur
if (!this.llama.isLeashed() && !this.llama.inCaravan()) {
List<Entity> list = this.llama.level().getEntities(this.llama, this.llama.getBoundingBox().inflate(9.0, 4.0, 9.0), entity -> {
EntityType<?> entityType = entity.getType();
@@ -71,6 +72,7 @@ public class LlamaFollowCaravanGoal extends Goal {
@Override
public boolean canContinueToUse() {
+ if (!this.llama.shouldJoinCaravan) return false; // Purpur
if (this.llama.inCaravan() && this.llama.getCaravanHead().isAlive() && this.firstIsLeashed(this.llama, 0)) {
double d = this.llama.distanceToSqr(this.llama.getCaravanHead());
if (d > 676.0) {
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
index 697895661826e4a1ecbdfd2c3a195b9d0ee7e00a..05614fb50a5509331ac15bb819e827365a4cefcf 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
@@ -75,6 +75,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
private Llama caravanHead;
@Nullable
public Llama caravanTail; // Paper
+ public boolean shouldJoinCaravan = true; // Purpur
public Llama(EntityType<? extends Llama> type, Level world) {
super(type, world);
@@ -167,6 +168,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
super.addAdditionalSaveData(nbt);
nbt.putInt("Variant", this.getVariant().id);
nbt.putInt("Strength", this.getStrength());
+ nbt.putBoolean("Purpur.ShouldJoinCaravan", shouldJoinCaravan); // Purpur
}
@Override
@@ -174,6 +176,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
this.setStrength(nbt.getInt("Strength"));
super.readAdditionalSaveData(nbt);
this.setVariant(Llama.Variant.byId(nbt.getInt("Variant")));
+ if (nbt.contains("Purpur.ShouldJoinCaravan")) this.shouldJoinCaravan = nbt.getBoolean("Purpur.ShouldJoinCaravan"); // Purpur
}
@Override
@@ -460,6 +463,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
public void leaveCaravan() {
if (this.caravanHead != null) {
+ new org.purpurmc.purpur.event.entity.LlamaLeaveCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity()).callEvent(); // Purpur
this.caravanHead.caravanTail = null;
}
@@ -467,6 +471,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
}
public void joinCaravan(Llama llama) {
+ if (!shouldJoinCaravan || !new org.purpurmc.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) llama.getBukkitEntity()).callEvent()) return; // Purpur
this.caravanHead = llama;
this.caravanHead.caravanTail = this;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
index 0ad16ee7b33582d214dab41eeee378d52c8e38ed..16bd1294c219f15ada653ef810bc2d748222d0da 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
@@ -90,4 +90,16 @@ public class CraftLlama extends CraftChestedHorse implements Llama, com.destroys
return this.getHandle().caravanTail == null ? null : (Llama) this.getHandle().caravanTail.getBukkitEntity();
}
// Paper end
+
+ // Purpur start
+ @Override
+ public boolean shouldJoinCaravan() {
+ return getHandle().shouldJoinCaravan;
+ }
+
+ @Override
+ public void setShouldJoinCaravan(boolean shouldJoinCaravan) {
+ getHandle().shouldJoinCaravan = shouldJoinCaravan;
+ }
+ // Purpur end
}

View File

@@ -1,330 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 8 Aug 2019 15:29:15 -0500
Subject: [PATCH] AFK API
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 2820333cbcd2cb972c4408cb0d9cc1be37a844cf..bc6a5de72d52627b3ceca4b52b95e12ceddf1247 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -2326,8 +2326,68 @@ public class ServerPlayer extends Player {
public void resetLastActionTime() {
this.lastActionTime = Util.getMillis();
+ this.setAfk(false); // Purpur
}
+ // Purpur Start
+ private boolean isAfk = false;
+
+ @Override
+ public void setAfk(boolean afk) {
+ if (this.isAfk == afk) {
+ return;
+ }
+
+ String msg = afk ? org.purpurmc.purpur.PurpurConfig.afkBroadcastAway : org.purpurmc.purpur.PurpurConfig.afkBroadcastBack;
+
+ org.purpurmc.purpur.event.PlayerAFKEvent event = new org.purpurmc.purpur.event.PlayerAFKEvent(this.getBukkitEntity(), afk, this.level().purpurConfig.idleTimeoutKick, msg, !Bukkit.isPrimaryThread());
+ if (!event.callEvent() || event.shouldKick()) {
+ return;
+ }
+
+ this.isAfk = afk;
+
+ if (!afk) {
+ resetLastActionTime();
+ }
+
+ msg = event.getBroadcastMsg();
+ if (msg != null && !msg.isEmpty()) {
+ String playerName = this.getGameProfile().getName();
+ if (org.purpurmc.purpur.PurpurConfig.afkBroadcastUseDisplayName) {
+ net.kyori.adventure.text.Component playerDisplayNameComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getBukkitEntity().getDisplayName());
+ playerName = net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(playerDisplayNameComponent);
+ }
+ server.getPlayerList().broadcastMiniMessage(String.format(msg, playerName), false);
+ }
+
+ if (this.level().purpurConfig.idleTimeoutUpdateTabList) {
+ String scoreboardName = getScoreboardName();
+ String playerListName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(getBukkitEntity().playerListName());
+ String[] split = playerListName.split(scoreboardName);
+ String prefix = (split.length > 0 ? split[0] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix, "");
+ String suffix = (split.length > 1 ? split[1] : "").replace(org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, "");
+ if (afk) {
+ getBukkitEntity().setPlayerListName(org.purpurmc.purpur.PurpurConfig.afkTabListPrefix + prefix + scoreboardName + suffix + org.purpurmc.purpur.PurpurConfig.afkTabListSuffix, true);
+ } else {
+ getBukkitEntity().setPlayerListName(prefix + scoreboardName + suffix);
+ }
+ }
+
+ ((ServerLevel) this.level()).updateSleepingPlayerList();
+ }
+
+ @Override
+ public boolean isAfk() {
+ return this.isAfk;
+ }
+
+ @Override
+ public boolean canBeCollidedWith() {
+ return !this.isAfk() && super.canBeCollidedWith();
+ }
+ // Purpur End
+
public ServerStatsCounter getStats() {
return this.stats;
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1377d7abfe024b8ac977aa1a071b401836c3c048..510a4391463026dd0c896027a579a94174c24299 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -332,6 +332,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private boolean justTeleported = false;
// CraftBukkit end
+ // Purpur start
+ private final com.google.common.cache.LoadingCache<CraftPlayer, Boolean> kickPermissionCache = com.google.common.cache.CacheBuilder.newBuilder()
+ .maximumSize(1000)
+ .expireAfterWrite(1, java.util.concurrent.TimeUnit.MINUTES)
+ .build(
+ new com.google.common.cache.CacheLoader<>() {
+ @Override
+ public Boolean load(CraftPlayer player) {
+ return player.hasPermission("purpur.bypassIdleKick");
+ }
+ }
+ );
+ // Purpur end
+
@Override
public void tick() {
if (this.ackBlockChangesUpTo > -1) {
@@ -399,6 +413,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits
+ // Purpur start
+ this.player.setAfk(true);
+ if (!this.player.level().purpurConfig.idleTimeoutKick || (!Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK")) && kickPermissionCache.getUnchecked(this.player.getBukkitEntity()))) {
+ return;
+ }
+ // Purpur end
this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
}
@@ -658,6 +678,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.lastYaw = to.getYaw();
this.lastPitch = to.getPitch();
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur
+
Location oldTo = to.clone();
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
this.cserver.getPluginManager().callEvent(event);
@@ -1494,7 +1516,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
movedWrongly = true;
if (event.getLogWarning())
// Paper end
- ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
+ ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), d11); // Purpur
} // Paper
}
@@ -1562,6 +1584,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.lastYaw = to.getYaw();
this.lastPitch = to.getPitch();
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur
+
Location oldTo = to.clone();
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
this.cserver.getPluginManager().callEvent(event);
diff --git a/src/main/java/net/minecraft/server/players/SleepStatus.java b/src/main/java/net/minecraft/server/players/SleepStatus.java
index 823efad652d8ff9e96b99375b102fef6f017716e..caa8a69bde0c212c36dd990a67836ac2f95548c0 100644
--- a/src/main/java/net/minecraft/server/players/SleepStatus.java
+++ b/src/main/java/net/minecraft/server/players/SleepStatus.java
@@ -19,7 +19,7 @@ public class SleepStatus {
public boolean areEnoughDeepSleeping(int percentage, List<ServerPlayer> players) {
// CraftBukkit start
- int j = (int) players.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count();
+ int j = (int) players.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping || (eh.level().purpurConfig.idleTimeoutCountAsSleeping && eh.isAfk()); }).count(); // Purpur
boolean anyDeepSleep = players.stream().anyMatch(Player::isSleepingLongEnough);
return anyDeepSleep && j >= this.sleepersNeeded(percentage);
@@ -52,7 +52,7 @@ public class SleepStatus {
if (!entityplayer.isSpectator()) {
++this.activePlayers;
- if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit
+ if ((entityplayer.isSleeping() || entityplayer.fauxSleeping) || (entityplayer.level().purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk())) { // CraftBukkit // Purpur
++this.sleepingPlayers;
}
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index d8cc5614502db7025349e085381b6b32ad32296a..f1b9e83206cc67e6ef29ebe088351b0aaa5eb349 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -40,6 +40,7 @@ public final class EntitySelector {
return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks;
};
// Paper end - Ability to control player's insomnia and phantoms
+ public static Predicate<Player> notAfk = (player) -> !player.isAfk(); // Purpur
private EntitySelector() {}
// Paper start - Affects Spawning API
diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
index d2f0c3b26d4beedb49d86e0242d843590d469d02..7463eefb7d09ea55fe8780210e7e967c2fe7896d 100644
--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
@@ -64,6 +64,10 @@ public class TargetingConditions {
return false;
} else if (this.selector != null && !this.selector.test(targetEntity)) {
return false;
+ // Purpur start
+ } else if (!targetEntity.level().purpurConfig.idleTimeoutTargetPlayer && targetEntity instanceof net.minecraft.server.level.ServerPlayer player && player.isAfk()) {
+ return false;
+ // Purpur end
} else {
if (baseEntity == null) {
if (this.isCombat && (!targetEntity.canBeSeenAsEnemy() || targetEntity.level().getDifficulty() == Difficulty.PEACEFUL)) {
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 054c905085b70ba72a3b76649bf5a20106f239d1..cd0992ec6b70f88c17cf7492847ae7f35e9c1e0d 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -201,6 +201,13 @@ public abstract class Player extends LivingEntity {
public boolean fauxSleeping;
public int oldLevel = -1;
+ public void setAfk(boolean afk) {
+ }
+
+ public boolean isAfk() {
+ return false;
+ }
+
@Override
public CraftHumanEntity getBukkitEntity() {
return (CraftHumanEntity) super.getBukkitEntity();
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index ea0aee88c7d901034427db201c1b2430f8a1d522..1f28bfb435c1e4d97da713f96c452abab3fda91a 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -192,7 +192,7 @@ public interface EntityGetter {
default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) {
for (Player player : this.players()) {
- if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) {
+ if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player) && EntitySelector.notAfk.test(player)) { // Purpur
double d = player.distanceToSqr(x, y, z);
if (range < 0.0 || d < range * range) {
return true;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7f78db4e0331d0f4801807ed1242642ee940d0f8..a4e4babedbf5bbf09bfbabd4f55ecd6301dae302 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -574,10 +574,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setPlayerListName(String name) {
+ // Purpur start
+ setPlayerListName(name, false);
+ }
+ public void setPlayerListName(String name, boolean useMM) {
+ // Purpur end
if (name == null) {
name = this.getName();
}
- this.getHandle().listName = name.equals(this.getName()) ? null : CraftChatMessage.fromStringOrNull(name);
+ this.getHandle().listName = name.equals(this.getName()) ? null : useMM ? io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name)) : CraftChatMessage.fromStringOrNull(name); // Purpur
if (this.getHandle().connection == null) return; // Paper - Updates are possible before the player has fully joined
for (ServerPlayer player : (List<ServerPlayer>) this.server.getHandle().players) {
if (player.getBukkitEntity().canSee(this)) {
@@ -3528,5 +3533,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public boolean usesPurpurClient() {
return getHandle().purpurClient;
}
+
+ @Override
+ public boolean isAfk() {
+ return getHandle().isAfk();
+ }
+
+ @Override
+ public void setAfk(boolean setAfk) {
+ getHandle().setAfk(setAfk);
+ }
+
+ @Override
+ public void resetIdleTimer() {
+ getHandle().resetLastActionTime();
+ }
// Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 940438c4b86d38be618dca8af95e3a7bf97bfa3c..beab078faaa6ea72539fdfd626ec64ff800d030c 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -174,8 +174,18 @@ public class PurpurConfig {
}
public static String cannotRideMob = "<red>You cannot mount that mob";
+ public static String afkBroadcastAway = "<yellow><italic>%s is now AFK";
+ public static String afkBroadcastBack = "<yellow><italic>%s is no longer AFK";
+ public static boolean afkBroadcastUseDisplayName = false;
+ public static String afkTabListPrefix = "[AFK] ";
+ public static String afkTabListSuffix = "";
private static void messages() {
cannotRideMob = getString("settings.messages.cannot-ride-mob", cannotRideMob);
+ afkBroadcastAway = getString("settings.messages.afk-broadcast-away", afkBroadcastAway);
+ afkBroadcastBack = getString("settings.messages.afk-broadcast-back", afkBroadcastBack);
+ afkBroadcastUseDisplayName = getBoolean("settings.messages.afk-broadcast-use-display-name", afkBroadcastUseDisplayName);
+ afkTabListPrefix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-prefix", afkTabListPrefix)));
+ afkTabListSuffix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-suffix", afkTabListSuffix)));
}
public static int barrelRows = 3;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index e248395ad5f5f012aeefecf367d54f90cade0996..70f53ccb22de2c05c9ead68f8bd29d0b69d0993f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -90,6 +90,24 @@ public class PurpurWorldConfig {
return value.isEmpty() ? fallback : value;
}
+ public boolean idleTimeoutKick = true;
+ public boolean idleTimeoutTickNearbyEntities = true;
+ public boolean idleTimeoutCountAsSleeping = false;
+ public boolean idleTimeoutUpdateTabList = false;
+ public boolean idleTimeoutTargetPlayer = true;
+ private void playerSettings() {
+ if (PurpurConfig.version < 19) {
+ boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
+ set("gameplay-mechanics.player.idle-timeout.mods-target", null);
+ set("gameplay-mechanics.player.idle-timeout.mobs-target", oldVal);
+ }
+ idleTimeoutKick = System.getenv("PURPUR_FORCE_IDLE_KICK") == null ? getBoolean("gameplay-mechanics.player.idle-timeout.kick-if-idle", idleTimeoutKick) : Boolean.parseBoolean(System.getenv("PURPUR_FORCE_IDLE_KICK"));
+ idleTimeoutTickNearbyEntities = getBoolean("gameplay-mechanics.player.idle-timeout.tick-nearby-entities", idleTimeoutTickNearbyEntities);
+ idleTimeoutCountAsSleeping = getBoolean("gameplay-mechanics.player.idle-timeout.count-as-sleeping", idleTimeoutCountAsSleeping);
+ idleTimeoutUpdateTabList = getBoolean("gameplay-mechanics.player.idle-timeout.update-tab-list", idleTimeoutUpdateTabList);
+ idleTimeoutTargetPlayer = getBoolean("gameplay-mechanics.player.idle-timeout.mobs-target", idleTimeoutTargetPlayer);
+ }
+
public boolean babiesAreRidable = true;
public boolean untamedTamablesAreRidable = true;
public boolean useNightVisionWhenRiding = false;
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 3283ed99c35ffed6805567705e0518d9f84feedc..a9a39f0da7b09410d8171172a4219c7d509fdb99 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -201,6 +201,7 @@ public class ActivationRange
continue;
}
+ if (!player.level().purpurConfig.idleTimeoutTickNearbyEntities && player.isAfk()) continue; // Purpur
// Paper start
int worldHeight = world.getHeight();
ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, worldHeight, maxRange );

View File

@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 26 May 2019 15:19:14 -0500
Subject: [PATCH] Bring back server name
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
index 9d10cdacb3aed2c00dc60aeb6f2cbeb48905e21f..842f382de43df5d5c321422372ec30ccdd7859d7 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
@@ -56,6 +56,7 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
public final boolean onlineMode = this.get("online-mode", true);
public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false);
public final String serverIp = this.get("server-ip", "");
+ public final String serverName = this.get("server-name", "Unknown Server"); // Purpur
public final boolean spawnAnimals = this.get("spawn-animals", true);
public final boolean spawnNpcs = this.get("spawn-npcs", true);
public final boolean pvp = this.get("pvp", true);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 26eb9ff0f4e77230d1eae793398869e71999982b..c014528d7d2583fa0a3007c42ea9c16f2d0eb20c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -3293,4 +3293,11 @@ public final class CraftServer implements Server {
return this.potionBrewer;
}
// Paper end
+
+ // Purpur start
+ @Override
+ public String getServerName() {
+ return this.getProperties().serverName;
+ }
+ // Purpur end
}

View File

@@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sat, 21 Mar 2020 11:47:39 -0500
Subject: [PATCH] Configurable server mod name
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 73b77367039eb6a4445d1ef2d66fb3410e91f4b8..8a6f7681d97c48886f5a78b61763e718e56ec015 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1925,7 +1925,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@DontObfuscate
public String getServerModName() {
- return "Purpur"; // Purpur - Purpur > // Pufferfish > // Paper
+ return org.purpurmc.purpur.PurpurConfig.serverModName; // Purpur - Purpur > // Pufferfish > // Paper
}
public SystemReport fillSystemReport(SystemReport details) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 7312ae7323032a0ba3c47aa7bdfe5dffe9674535..881c5654f181ea9b66e1cdf3bc3bf46869e8557f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -188,6 +188,11 @@ public class PurpurConfig {
afkTabListSuffix = MiniMessage.miniMessage().serialize(MiniMessage.miniMessage().deserialize(getString("settings.messages.afk-tab-list-suffix", afkTabListSuffix)));
}
+ public static String serverModName = "Purpur";
+ private static void serverModName() {
+ serverModName = getString("settings.server-mod-name", serverModName);
+ }
+
public static int barrelRows = 3;
public static boolean enderChestSixRows = false;
public static boolean enderChestPermissionRows = false;

View File

@@ -1,57 +0,0 @@
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] Lagging threshold
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 8a6f7681d97c48886f5a78b61763e718e56ec015..dfa332c4ff52033eb95248518bc44bbd22697697 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -315,6 +315,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files
public static long currentTickLong = 0L; // Paper - track current tick as a long
public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
+ public boolean lagging = false; // Purpur
public volatile Thread shutdownThread; // Paper
public volatile boolean abnormalExit = false; // Paper
@@ -1215,6 +1216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.recentTps[0] = tps1.getAverage();
this.recentTps[1] = tps5.getAverage();
this.recentTps[2] = tps15.getAverage();
+ lagging = recentTps[0] < org.purpurmc.purpur.PurpurConfig.laggingThreshold; // Purpur
tickSection = currentTime;
}
// Paper end - further improve server tick loop
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index c014528d7d2583fa0a3007c42ea9c16f2d0eb20c..6d8b433af8596dd5b5a3b04e901527cd50a31dec 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -3299,5 +3299,10 @@ public final class CraftServer implements Server {
public String getServerName() {
return this.getProperties().serverName;
}
+
+ @Override
+ public boolean isLagging() {
+ return getServer().lagging;
+ }
// Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 881c5654f181ea9b66e1cdf3bc3bf46869e8557f..9c5bba0ae119f8d42274455e322530ceb5f67d9b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -193,6 +193,11 @@ public class PurpurConfig {
serverModName = getString("settings.server-mod-name", serverModName);
}
+ public static double laggingThreshold = 19.0D;
+ private static void tickLoopSettings() {
+ laggingThreshold = getDouble("settings.lagging-threshold", laggingThreshold);
+ }
+
public static int barrelRows = 3;
public static boolean enderChestSixRows = false;
public static boolean enderChestPermissionRows = false;

View File

@@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 5 Jul 2019 18:21:00 -0500
Subject: [PATCH] PlayerSetSpawnerTypeWithEggEvent
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index a46bf73c608641bf1f00fd55242de71a0f2ee06e..9b3bf5ac043262c6cd00d83b750c3313122d92a9 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -330,6 +330,16 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
return (EntityType) Registry.register(BuiltInRegistries.ENTITY_TYPE, id, (EntityType<T>) type.build(id)); // CraftBukkit - decompile error
}
+ // Purpur start
+ public static EntityType<?> getFromBukkitType(org.bukkit.entity.EntityType bukkitType) {
+ return getFromKey(new ResourceLocation(bukkitType.getKey().toString()));
+ }
+
+ public static EntityType<?> getFromKey(ResourceLocation location) {
+ return BuiltInRegistries.ENTITY_TYPE.get(location);
+ }
+ // Purpur end
+
public static ResourceLocation getKey(EntityType<?> type) {
return BuiltInRegistries.ENTITY_TYPE.getKey(type);
}
@@ -537,6 +547,16 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
return this.category;
}
+ // Purpur start
+ public String getName() {
+ return BuiltInRegistries.ENTITY_TYPE.getKey(this).getPath();
+ }
+
+ public String getTranslatedName() {
+ return getDescription().getString();
+ }
+ // Purpur end
+
public String getDescriptionId() {
if (this.descriptionId == null) {
this.descriptionId = Util.makeDescriptionId("entity", BuiltInRegistries.ENTITY_TYPE.getKey(this));
diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
index 9cea8da84f39bb3f687139ef213ccea358724dee..076e6858222b92f8409f1f5cad398582c1fd6bcb 100644
--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java
+++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
@@ -74,6 +74,15 @@ public class SpawnEggItem extends Item {
Spawner spawner = (Spawner) tileentity;
entitytypes = this.getType(itemstack);
+
+ // Purpur start
+ org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent event = new org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), bukkitBlock, (org.bukkit.block.CreatureSpawner) bukkitBlock.getState(), org.bukkit.entity.EntityType.fromName(entitytypes.getName()));
+ if (!event.callEvent()) {
+ return InteractionResult.FAIL;
+ }
+ entitytypes = EntityType.getFromBukkitType(event.getEntityType());
+ // Purpur end
spawner.setEntityId(entitytypes, world.getRandom());
world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3);
world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.BLOCK_CHANGE, blockposition);

View File

@@ -1,173 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 19 Apr 2020 00:17:56 -0500
Subject: [PATCH] Anvil API
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 32910f677b0522ac8ec513fa0d00b714b52cfae4..f85eef14b91a0ada1f6f4b13ab3966f051ff92d3 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -76,6 +76,7 @@ public abstract class AbstractContainerMenu {
@Nullable
private ContainerSynchronizer synchronizer;
private boolean suppressRemoteUpdates;
+ @javax.annotation.Nullable protected ItemStack activeQuickItem = null; // Purpur
// CraftBukkit start
public boolean checkReachable = true;
diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
index 2bd91b48eaa06f85a5b9b1ae052c70e966ae8e4c..9036426256f87b3ba4a78e6fa2cea4e028f84481 100644
--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
@@ -25,6 +25,13 @@ import org.slf4j.Logger;
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
// CraftBukkit end
+// Purpur start
+import net.minecraft.nbt.IntTag;
+import net.minecraft.network.protocol.game.ClientboundContainerSetDataPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.server.level.ServerPlayer;
+// Purpur end
+
public class AnvilMenu extends ItemCombinerMenu {
public static final int INPUT_SLOT = 0;
@@ -53,6 +60,8 @@ public class AnvilMenu extends ItemCombinerMenu {
public int maximumRepairCost = 40;
private CraftInventoryView bukkitEntity;
// CraftBukkit end
+ public boolean bypassCost = false; // Purpur
+ public boolean canDoUnsafeEnchants = false; // Purpur
public AnvilMenu(int syncId, Inventory inventory) {
this(syncId, inventory, ContainerLevelAccess.NULL);
@@ -80,12 +89,15 @@ public class AnvilMenu extends ItemCombinerMenu {
@Override
protected boolean mayPickup(Player player, boolean present) {
- return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && present; // CraftBukkit - allow cost 0 like a free item
+ return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && (bypassCost || this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST) && present; // CraftBukkit - allow cost 0 like a free item // Purpur
}
@Override
protected void onTake(Player player, ItemStack stack) {
+ ItemStack itemstack = activeQuickItem == null ? stack : activeQuickItem; // Purpur
+ if (org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent.getHandlerList().getRegisteredListeners().length > 0) new org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)).callEvent(); // Purpur
if (!player.getAbilities().instabuild) {
+ if (bypassCost) ((ServerPlayer) player).lastSentExp = -1; else // Purpur
player.giveExperienceLevels(-this.cost.get());
}
@@ -136,6 +148,12 @@ public class AnvilMenu extends ItemCombinerMenu {
@Override
public void createResult() {
+ // Purpur start
+ bypassCost = false;
+ canDoUnsafeEnchants = false;
+ if (org.purpurmc.purpur.event.inventory.AnvilUpdateResultEvent.getHandlerList().getRegisteredListeners().length > 0) new org.purpurmc.purpur.event.inventory.AnvilUpdateResultEvent(getBukkitView()).callEvent();
+ // Purpur end
+
ItemStack itemstack = this.inputSlots.getItem(0);
this.cost.set(1);
@@ -143,7 +161,7 @@ public class AnvilMenu extends ItemCombinerMenu {
long j = 0L;
byte b0 = 0;
- if (!itemstack.isEmpty() && EnchantmentHelper.canStoreEnchantments(itemstack)) {
+ if (!itemstack.isEmpty() && canDoUnsafeEnchants || EnchantmentHelper.canStoreEnchantments(itemstack)) { // Purpur
ItemStack itemstack1 = itemstack.copy();
ItemStack itemstack2 = this.inputSlots.getItem(1);
ItemEnchantments.Mutable itemenchantments_a = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(itemstack1));
@@ -222,7 +240,7 @@ public class AnvilMenu extends ItemCombinerMenu {
Holder<Enchantment> holder1 = (Holder) iterator1.next();
if (!holder1.equals(holder) && !enchantment.isCompatibleWith((Enchantment) holder1.value())) {
- flag3 = false;
+ flag3 = canDoUnsafeEnchants; // Purpur
++i;
}
}
@@ -280,6 +298,12 @@ public class AnvilMenu extends ItemCombinerMenu {
this.cost.set(this.maximumRepairCost - 1); // CraftBukkit
}
+ // Purpur start
+ if (bypassCost && cost.get() >= maximumRepairCost) {
+ cost.set(maximumRepairCost - 1);
+ }
+ // Purpur end
+
if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit
itemstack1 = ItemStack.EMPTY;
}
@@ -301,6 +325,12 @@ public class AnvilMenu extends ItemCombinerMenu {
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemstack1); // CraftBukkit
this.sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client
this.broadcastChanges();
+ // Purpur start
+ if (canDoUnsafeEnchants && itemstack1 != ItemStack.EMPTY) {
+ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 2, itemstack1));
+ ((ServerPlayer) player).connection.send(new ClientboundContainerSetDataPacket(containerId, 0, cost.get()));
+ }
+ // Purpur end
} else {
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit
this.cost.set(AnvilMenu.DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item
diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
index 7de5e47f9a54263734eeef855a2dc07ef64d30ea..7215af6cc91f48b040c23c54536d4aac8d293497 100644
--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -178,7 +178,9 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
return ItemStack.EMPTY;
}
+ this.activeQuickItem = itemstack; // Purpur
slot1.onTake(player, itemstack1);
+ this.activeQuickItem = null; // Purpur
}
return itemstack;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
index 9ee14589d63bbfc0880f2eee5e924fe946ee0035..0a5841fa26698e60bdeadbb58b9343fe1ff08a28 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java
@@ -9,7 +9,7 @@ import org.bukkit.inventory.AnvilInventory;
public class CraftInventoryAnvil extends CraftResultInventory implements AnvilInventory {
private final Location location;
- private final AnvilMenu container;
+ public final AnvilMenu container; // Purpur - private -> public
public CraftInventoryAnvil(Location location, Container inventory, Container resultInventory, AnvilMenu container) {
super(inventory, resultInventory);
@@ -57,4 +57,26 @@ public class CraftInventoryAnvil extends CraftResultInventory implements AnvilIn
Preconditions.checkArgument(levels >= 0, "Maximum repair cost must be positive (or 0)");
this.container.maximumRepairCost = levels;
}
+
+ // Purpur start
+ @Override
+ public boolean canBypassCost() {
+ return container.bypassCost;
+ }
+
+ @Override
+ public void setBypassCost(boolean bypassCost) {
+ container.bypassCost = bypassCost;
+ }
+
+ @Override
+ public boolean canDoUnsafeEnchants() {
+ return container.canDoUnsafeEnchants;
+ }
+
+ @Override
+ public void setDoUnsafeEnchants(boolean canDoUnsafeEnchants) {
+ container.canDoUnsafeEnchants = canDoUnsafeEnchants;
+ }
+ // Purpur end
}

View File

@@ -1,73 +0,0 @@
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] Alternative Keepalive Handling
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 4228fd441f8350d43bd545e31c920304f07968bc..3a15085e0421f46800f779066d235ef21b463289 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -73,6 +73,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
private long keepAliveChallenge;
private long closedListenerTime;
private boolean closed = false;
+ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur
private int latency;
private volatile boolean suspendFlushingOnServerThread = false;
public final java.util.Map<java.util.UUID, net.kyori.adventure.resource.ResourcePackCallback> packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
@@ -124,6 +125,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@Override
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) {
+ long id = packet.getId();
+ if (keepAlives.size() > 0 && keepAlives.contains(id)) {
+ int ping = (int) (Util.getMillis() - id);
+ this.latency = (this.latency * 3 + ping) / 4;
+ keepAlives.clear(); // we got a valid response, lets roll with it and forget the rest
+ }
+ } else
+ // Purpur end
//PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - handle ServerboundKeepAlivePacket async
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
int i = (int) (Util.getMillis() - this.keepAliveTime);
@@ -260,6 +271,21 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
long currentTime = Util.getMillis();
long elapsedTime = currentTime - this.keepAliveTime;
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) {
+ if (elapsedTime >= 1000L) { // 1 second
+ if (!processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) {
+ LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName());
+ disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
+ } else {
+ keepAliveTime = currentTime; // hijack this field for 1 second intervals
+ keepAlives.add(currentTime); // currentTime is ID
+ send(new ClientboundKeepAlivePacket(currentTime));
+ }
+ }
+ } else
+ // Purpur end
+
if (!this.isSingleplayerOwner() && elapsedTime >= KEEPALIVE_LIMIT) { // Paper - check keepalive limit, don't fire if already disconnected
if (this.keepAlivePending && !this.processedDisconnect) { // Paper
this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 9c5bba0ae119f8d42274455e322530ceb5f67d9b..a14cf3a5dc2ba265de5e400404afcbd9faa3f25a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -198,6 +198,11 @@ public class PurpurConfig {
laggingThreshold = getDouble("settings.lagging-threshold", laggingThreshold);
}
+ public static boolean useAlternateKeepAlive = false;
+ private static void useAlternateKeepAlive() {
+ useAlternateKeepAlive = getBoolean("settings.use-alternate-keepalive", useAlternateKeepAlive);
+ }
+
public static int barrelRows = 3;
public static boolean enderChestSixRows = false;
public static boolean enderChestPermissionRows = false;

View File

@@ -1,190 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 9 May 2019 14:27:37 -0500
Subject: [PATCH] Silk touch spawners
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 96fb69ec6db2e7c8c728435f0c537b076259b2fb..3253361d91e2a2e68d354eaf3dd3e3cd486e191d 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -219,6 +219,7 @@ public class BlockItem extends Item {
if (tileentity != null) {
if (!world.isClientSide && tileentity.onlyOpCanSetNbt() && (player == null || !(player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place"))))) { // Spigot - add permission
+ if (!(!world.isClientSide && world.purpurConfig.silkTouchEnabled && tileentity instanceof net.minecraft.world.level.block.entity.SpawnerBlockEntity && player.getBukkitEntity().hasPermission("purpur.drop.spawners")))
return false;
}
diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java
index d00b59efb754594cf532f8598f4b6d3b29693232..6467358f5fdf4cd4f7c1e2cc65c834a9da39596a 100644
--- a/src/main/java/net/minecraft/world/item/Items.java
+++ b/src/main/java/net/minecraft/world/item/Items.java
@@ -338,7 +338,7 @@ public class Items {
public static final Item PURPUR_BLOCK = registerBlock(Blocks.PURPUR_BLOCK);
public static final Item PURPUR_PILLAR = registerBlock(Blocks.PURPUR_PILLAR);
public static final Item PURPUR_STAIRS = registerBlock(Blocks.PURPUR_STAIRS);
- public static final Item SPAWNER = registerBlock(Blocks.SPAWNER);
+ public static final Item SPAWNER = registerBlock(new org.purpurmc.purpur.item.SpawnerItem(Blocks.SPAWNER, new Item.Properties().rarity(Rarity.EPIC))); // Purpur
public static final Item CHEST = registerBlock(Blocks.CHEST, settings -> settings.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY));
public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE);
public static final Item FARMLAND = registerBlock(Blocks.FARMLAND);
diff --git a/src/main/java/net/minecraft/world/level/block/SpawnerBlock.java b/src/main/java/net/minecraft/world/level/block/SpawnerBlock.java
index 4f190a40b8474aa06a92c8afcc06d0044120ff7b..66c17bdfecdfbcfb2d853e561432dd51a8f7ed46 100644
--- a/src/main/java/net/minecraft/world/level/block/SpawnerBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SpawnerBlock.java
@@ -42,6 +42,57 @@ public class SpawnerBlock extends BaseEntityBlock {
return createTickerHelper(type, BlockEntityType.MOB_SPAWNER, world.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick);
}
+ // Purpur start
+ @Override
+ public void playerDestroy(Level level, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack, boolean includeDrops, boolean dropExp) {
+ if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.drop.spawners") && isSilkTouch(level, stack)) {
+ ItemStack item = new ItemStack(Blocks.SPAWNER.asItem());
+
+ net.minecraft.world.level.SpawnData nextSpawnData = blockEntity instanceof SpawnerBlockEntity spawnerBlock ? spawnerBlock.getSpawner().nextSpawnData : null;
+ java.util.Optional<net.minecraft.world.entity.EntityType<?>> type = java.util.Optional.empty();
+ if (nextSpawnData != null) {
+ type = net.minecraft.world.entity.EntityType.by(nextSpawnData.getEntityToSpawn());
+ net.minecraft.world.level.SpawnData.CODEC.encodeStart(net.minecraft.nbt.NbtOps.INSTANCE, nextSpawnData).result().ifPresent(tag -> item.set(net.minecraft.core.component.DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY.update(compoundTag -> compoundTag.put("Purpur.SpawnData", tag))));
+ }
+
+ if (type.isPresent()) {
+ final net.kyori.adventure.text.Component mobName = io.papermc.paper.adventure.PaperAdventure.asAdventure(type.get().getDescription());
+
+ String name = level.purpurConfig.silkTouchSpawnerName;
+ if (name != null && !name.isEmpty() && !name.equals("Monster Spawner")) {
+ net.kyori.adventure.text.Component displayName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName));
+ if (name.startsWith("<reset>")) {
+ displayName = displayName.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false);
+ }
+ item.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName));
+ }
+
+ List<String> lore = level.purpurConfig.silkTouchSpawnerLore;
+ if (lore != null && !lore.isEmpty()) {
+
+ List<Component> loreComponentList = new java.util.ArrayList<>();
+ for (String line : lore) {
+ net.kyori.adventure.text.Component lineComponent = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(line, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName));
+ if (line.startsWith("<reset>")) {
+ lineComponent = lineComponent.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false);
+ }
+ loreComponentList.add(io.papermc.paper.adventure.PaperAdventure.asVanilla(lineComponent));
+ }
+
+ item.set(net.minecraft.core.component.DataComponents.LORE, new net.minecraft.world.item.component.ItemLore(loreComponentList, loreComponentList));
+ }
+ item.set(net.minecraft.core.component.DataComponents.HIDE_ADDITIONAL_TOOLTIP, net.minecraft.util.Unit.INSTANCE);
+ }
+ popResource(level, pos, item);
+ }
+ super.playerDestroy(level, player, pos, state, blockEntity, stack, includeDrops, dropExp);
+ }
+
+ private boolean isSilkTouch(Level level, ItemStack stack) {
+ return stack != null && level.purpurConfig.silkTouchTools.contains(stack.getItem()) && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.SILK_TOUCH, stack) >= level.purpurConfig.minimumSilkTouchSpawnerRequire;
+ }
+ // Purpur end
+
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
super.spawnAfterBreak(state, world, pos, tool, dropExperience);
@@ -50,6 +101,7 @@ public class SpawnerBlock extends BaseEntityBlock {
@Override
public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ if (isSilkTouch(worldserver, itemstack)) return 0; // Purpur
if (flag) {
int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 70f53ccb22de2c05c9ead68f8bd29d0b69d0993f..d4bca5b5f3d10c3a04befd8c365f46433491f299 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -108,6 +108,38 @@ public class PurpurWorldConfig {
idleTimeoutTargetPlayer = getBoolean("gameplay-mechanics.player.idle-timeout.mobs-target", idleTimeoutTargetPlayer);
}
+ public boolean silkTouchEnabled = false;
+ public String silkTouchSpawnerName = "<reset><white>Monster Spawner";
+ public List<String> silkTouchSpawnerLore = new ArrayList<>();
+ public List<Item> silkTouchTools = new ArrayList<>();
+ public int minimumSilkTouchSpawnerRequire = 1;
+ private void silkTouchSettings() {
+ if (PurpurConfig.version < 21) {
+ String oldName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName);
+ set("gameplay-mechanics.silk-touch.spawner-name", "<reset>" + ChatColor.toMM(oldName.replace("{mob}", "<mob>")));
+ List<String> list = new ArrayList<>();
+ getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a <mob>"))
+ .forEach(line -> list.add("<reset>" + ChatColor.toMM(line.toString().replace("{mob}", "<mob>"))));
+ set("gameplay-mechanics.silk-touch.spawner-lore", list);
+ }
+ silkTouchEnabled = getBoolean("gameplay-mechanics.silk-touch.enabled", silkTouchEnabled);
+ silkTouchSpawnerName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName);
+ minimumSilkTouchSpawnerRequire = getInt("gameplay-mechanics.silk-touch.minimal-level", minimumSilkTouchSpawnerRequire);
+ silkTouchSpawnerLore.clear();
+ getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a <mob>"))
+ .forEach(line -> silkTouchSpawnerLore.add(line.toString()));
+ silkTouchTools.clear();
+ getList("gameplay-mechanics.silk-touch.tools", List.of(
+ "minecraft:iron_pickaxe",
+ "minecraft:golden_pickaxe",
+ "minecraft:diamond_pickaxe",
+ "minecraft:netherite_pickaxe"
+ )).forEach(key -> {
+ Item item = BuiltInRegistries.ITEM.get(new ResourceLocation(key.toString()));
+ if (item != Items.AIR) silkTouchTools.add(item);
+ });
+ }
+
public boolean babiesAreRidable = true;
public boolean untamedTamablesAreRidable = true;
public boolean useNightVisionWhenRiding = false;
diff --git a/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java b/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed50cb2115401c9039df4136caf5a087a5f5991c
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java
@@ -0,0 +1,40 @@
+package org.purpurmc.purpur.item;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.BlockItem;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+
+public class SpawnerItem extends BlockItem {
+
+ public SpawnerItem(Block block, Properties settings) {
+ super(block, settings);
+ }
+
+ @Override
+ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, Player player, ItemStack stack, BlockState state) {
+ boolean handled = super.updateCustomBlockEntityTag(pos, level, player, stack, state);
+ if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.place.spawners")) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof SpawnerBlockEntity spawner) {
+ CompoundTag customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
+ if (customData.contains("Purpur.mob_type")) {
+ EntityType.byString(customData.getString("Purpur.mob_type")).ifPresent(type -> spawner.getSpawner().setEntityId(type, level, level.random, pos));
+ } else if (customData.contains("Purpur.SpawnData")) {
+ net.minecraft.world.level.SpawnData.CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, customData.getCompound("Purpur.SpawnData")).result()
+ .ifPresent(spawnData -> spawner.getSpawner().nextSpawnData = spawnData);
+ }
+ }
+ }
+ return handled;
+ }
+}

View File

@@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 6 Jun 2019 22:15:46 -0500
Subject: [PATCH] Add turtle egg block options
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
index a6f408e56fa6c9de82fd93555fe21e1b11ce1022..c7377d04ceac3ea624117439783a443c6d6f6d08 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -203,6 +203,25 @@ public class TurtleEggBlock extends Block {
}
private boolean canDestroyEgg(Level world, Entity entity) {
- return !(entity instanceof Turtle) && !(entity instanceof Bat) ? (!(entity instanceof LivingEntity) ? false : entity instanceof Player || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) : false;
+ // Purpur start
+ if (entity instanceof Turtle || entity instanceof Bat) {
+ return false;
+ }
+ if (world.purpurConfig.turtleEggsBreakFromExpOrbs && entity instanceof net.minecraft.world.entity.ExperienceOrb) {
+ return true;
+ }
+ if (world.purpurConfig.turtleEggsBreakFromItems && entity instanceof net.minecraft.world.entity.item.ItemEntity) {
+ return true;
+ }
+ if (world.purpurConfig.turtleEggsBreakFromMinecarts && entity instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) {
+ return true;
+ }
+ if (!(entity instanceof LivingEntity)) {
+ return false;
+ }
+ if (entity instanceof Player) return true;
+
+ return world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
+ // Purpur end
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index d4bca5b5f3d10c3a04befd8c365f46433491f299..ac44ee7789b96e60e6d1d964d64ca33a3d3c2c62 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -140,6 +140,15 @@ public class PurpurWorldConfig {
});
}
+ public boolean turtleEggsBreakFromExpOrbs = false;
+ public boolean turtleEggsBreakFromItems = false;
+ public boolean turtleEggsBreakFromMinecarts = false;
+ private void turtleEggSettings() {
+ turtleEggsBreakFromExpOrbs = getBoolean("blocks.turtle_egg.break-from-exp-orbs", turtleEggsBreakFromExpOrbs);
+ turtleEggsBreakFromItems = getBoolean("blocks.turtle_egg.break-from-items", turtleEggsBreakFromItems);
+ turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts);
+ }
+
public boolean babiesAreRidable = true;
public boolean untamedTamablesAreRidable = true;
public boolean useNightVisionWhenRiding = false;

View File

@@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 19 Oct 2019 00:52:12 -0500
Subject: [PATCH] Logger settings (suppressing pointless logs)
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
index c7e1f2bac3eca9bb72bf1f8c26cccb2905e1ddfc..94893039363b5fe2d7d0622d0592bce2c867b1c3 100644
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
@@ -199,6 +199,7 @@ public class PlayerAdvancements {
if (advancementholder == null) {
if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressIgnoredAdvancementWarnings) // Purpur
PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath);
} else {
this.startProgress(advancementholder, advancementprogress);
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
index 1351423a12c19a01f602a202832372a399e6a867..1e2025674eafcf56460c741083c91e2e42d61b19 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -326,6 +326,7 @@ public class WorldGenRegion implements WorldGenLevel {
return true;
} else {
// Paper start - Buffer OOB setBlock calls
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressSetBlockFarChunk) // Purpur
if (!hasSetFarWarned) {
Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + String.valueOf(pos) + ", status: " + String.valueOf(this.generatingStatus) + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get()));
hasSetFarWarned = true;
diff --git a/src/main/java/net/minecraft/stats/ServerRecipeBook.java b/src/main/java/net/minecraft/stats/ServerRecipeBook.java
index 4103ddf16164e3992fef0765d368282572537e29..a0cb49233b1dbf53ce9d1bcc52b8967829d0530e 100644
--- a/src/main/java/net/minecraft/stats/ServerRecipeBook.java
+++ b/src/main/java/net/minecraft/stats/ServerRecipeBook.java
@@ -125,6 +125,7 @@ public class ServerRecipeBook extends RecipeBook {
Optional<RecipeHolder<?>> optional = recipeManager.byKey(minecraftkey);
if (optional.isEmpty()) {
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressUnrecognizedRecipeErrors) // Purpur
ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", minecraftkey);
} else {
handler.accept((RecipeHolder) optional.get());
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
index 71d057dc8c7362f8e7aaca5e31c9f02b2bf3f281..9d9405af0db28c0f3ffff2881b54f1dc84675a9d 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
@@ -256,6 +256,7 @@ public final class CraftLegacy {
}
static {
+ if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressInitLegacyMaterialError) // Purpur
LOGGER.warn("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!"); // Paper - Improve logging and errors; doesn't need to be an error
if (MinecraftServer.getServer() != null && MinecraftServer.getServer().isDebugging()) {
new Exception().printStackTrace();
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index a14cf3a5dc2ba265de5e400404afcbd9faa3f25a..a14879f4266c71b7493c05e105114590c6709045 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -237,4 +237,15 @@ public class PurpurConfig {
org.bukkit.event.inventory.InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27);
enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows);
}
+
+ public static boolean loggerSuppressInitLegacyMaterialError = false;
+ public static boolean loggerSuppressIgnoredAdvancementWarnings = false;
+ public static boolean loggerSuppressUnrecognizedRecipeErrors = false;
+ public static boolean loggerSuppressSetBlockFarChunk = false;
+ private static void loggerSettings() {
+ loggerSuppressInitLegacyMaterialError = getBoolean("settings.logger.suppress-init-legacy-material-errors", loggerSuppressInitLegacyMaterialError);
+ loggerSuppressIgnoredAdvancementWarnings = getBoolean("settings.logger.suppress-ignored-advancement-warnings", loggerSuppressIgnoredAdvancementWarnings);
+ loggerSuppressUnrecognizedRecipeErrors = getBoolean("settings.logger.suppress-unrecognized-recipe-errors", loggerSuppressUnrecognizedRecipeErrors);
+ loggerSuppressSetBlockFarChunk = getBoolean("settings.logger.suppress-setblock-in-far-chunk-errors", loggerSuppressSetBlockFarChunk);
+ }
}

View File

@@ -1,133 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 12 May 2019 00:43:12 -0500
Subject: [PATCH] Giants AI settings
diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java
index 9602e59cbebeedc85ea75d2a41d3e74f0ff45b46..3c1217d36522b1fd3d1a099d3a12d99016f34c4b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Giant.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java
@@ -1,11 +1,34 @@
package net.minecraft.world.entity.monster;
import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.Difficulty;
+import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.MobSpawnType;
+import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
+import net.minecraft.world.entity.ai.goal.FloatGoal;
+import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
+import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
+import net.minecraft.world.entity.ai.goal.MoveTowardsRestrictionGoal;
+import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
+import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
+import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
+import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
+import net.minecraft.world.entity.animal.IronGolem;
+import net.minecraft.world.entity.animal.Turtle;
+import net.minecraft.world.entity.npc.Villager;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
+import net.minecraft.world.level.ServerLevelAccessor;
+
+import javax.annotation.Nullable;
public class Giant extends Monster {
public Giant(EntityType<? extends Giant> type, Level world) {
@@ -30,8 +53,23 @@ public class Giant extends Monster {
@Override
protected void registerGoals() {
- this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
- this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
+ if (level().purpurConfig.giantHaveAI) {
+ this.goalSelector.addGoal(0, new FloatGoal(this));
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
+ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
+ this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 16.0F));
+ this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
+ this.goalSelector.addGoal(5, new MoveTowardsRestrictionGoal(this, 1.0D));
+ if (level().purpurConfig.giantHaveHostileAI) {
+ this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false));
+ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this));
+ this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class));
+ this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
+ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Villager.class, false));
+ this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
+ this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, true));
+ }
+ }
}
@Override
@@ -47,8 +85,34 @@ public class Giant extends Monster {
return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 100.0).add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.ATTACK_DAMAGE, 50.0);
}
+ @Override
+ public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) {
+ SpawnGroupData groupData = super.finalizeSpawn(world, difficulty, spawnReason, entityData);
+ if (groupData == null) {
+ populateDefaultEquipmentSlots(this.random, difficulty);
+ populateDefaultEquipmentEnchantments(this.random, difficulty);
+ }
+ return groupData;
+ }
+
+ @Override
+ protected void populateDefaultEquipmentSlots(net.minecraft.util.RandomSource random, DifficultyInstance difficulty) {
+ super.populateDefaultEquipmentSlots(this.random, difficulty);
+ // TODO make configurable
+ if (random.nextFloat() < (level().getDifficulty() == Difficulty.HARD ? 0.1F : 0.05F)) {
+ this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD));
+ }
+ }
+
+ @Override
+ public float getJumpPower() {
+ // make giants jump as high as everything else relative to their size
+ // 1.0 makes bottom of feet about as high as their waist when they jump
+ return level().purpurConfig.giantJumpHeight;
+ }
+
@Override
public float getWalkTargetValue(BlockPos pos, LevelReader world) {
- return world.getPathfindingCostFromLightLevels(pos);
+ return super.getWalkTargetValue(pos, world); // Purpur - fix light requirements for natural spawns
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index ac44ee7789b96e60e6d1d964d64ca33a3d3c2c62..fb61cd498955fee2dec15fa584273a6e19ca58c9 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -554,6 +554,10 @@ public class PurpurWorldConfig {
public double giantMovementSpeed = 0.5D;
public double giantAttackDamage = 50.0D;
public double giantMaxHealth = 100.0D;
+ public float giantStepHeight = 2.0F;
+ public float giantJumpHeight = 1.0F;
+ public boolean giantHaveAI = false;
+ public boolean giantHaveHostileAI = false;
private void giantSettings() {
giantRidable = getBoolean("mobs.giant.ridable", giantRidable);
giantRidableInWater = getBoolean("mobs.giant.ridable-in-water", giantRidableInWater);
@@ -570,6 +574,10 @@ public class PurpurWorldConfig {
set("mobs.giant.attributes.max_health", oldValue);
}
giantMaxHealth = getDouble("mobs.giant.attributes.max_health", giantMaxHealth);
+ giantStepHeight = (float) getDouble("mobs.giant.step-height", giantStepHeight);
+ giantJumpHeight = (float) getDouble("mobs.giant.jump-height", giantJumpHeight);
+ giantHaveAI = getBoolean("mobs.giant.have-ai", giantHaveAI);
+ giantHaveHostileAI = getBoolean("mobs.giant.have-hostile-ai", giantHaveHostileAI);
}
public boolean glowSquidRidable = false;

View File

@@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sun, 7 Jul 2019 19:52:16 -0500
Subject: [PATCH] Zombie horse naturally spawn
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index fc791a66d299905798c2c1ca542467e4c7933caf..b02d9db8442b209a9df27e417be71b11d426878b 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1006,10 +1006,18 @@ public class ServerLevel extends Level implements WorldGenLevel {
boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01D) && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper - Configurable spawn chances for skeleton horses
if (flag1) {
- SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this);
+ // Purpur start
+ net.minecraft.world.entity.animal.horse.AbstractHorse entityhorseskeleton;
+ if (purpurConfig.zombieHorseSpawnChance > 0D && random.nextDouble() <= purpurConfig.zombieHorseSpawnChance) {
+ entityhorseskeleton = EntityType.ZOMBIE_HORSE.create(this);
+ } else {
+ entityhorseskeleton = EntityType.SKELETON_HORSE.create(this);
+ if (entityhorseskeleton != null) ((SkeletonHorse) entityhorseskeleton).setTrap(true);
+ }
+ // Purpur end
if (entityhorseskeleton != null) {
- entityhorseskeleton.setTrap(true);
+ //entityhorseskeleton.setTrap(true); // Purpur - moved up
entityhorseskeleton.setAge(0);
entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index fb61cd498955fee2dec15fa584273a6e19ca58c9..41822b9b050f4267cc0151ea85682523f89af57f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1487,6 +1487,7 @@ public class PurpurWorldConfig {
public double zombieHorseJumpStrengthMax = 1.0D;
public double zombieHorseMovementSpeedMin = 0.2D;
public double zombieHorseMovementSpeedMax = 0.2D;
+ public double zombieHorseSpawnChance = 0.0D;
private void zombieHorseSettings() {
zombieHorseRidable = getBoolean("mobs.zombie_horse.ridable", zombieHorseRidable);
zombieHorseRidableInWater = getBoolean("mobs.zombie_horse.ridable-in-water", zombieHorseRidableInWater);
@@ -1503,6 +1504,7 @@ public class PurpurWorldConfig {
zombieHorseJumpStrengthMax = getDouble("mobs.zombie_horse.attributes.jump_strength.max", zombieHorseJumpStrengthMax);
zombieHorseMovementSpeedMin = getDouble("mobs.zombie_horse.attributes.movement_speed.min", zombieHorseMovementSpeedMin);
zombieHorseMovementSpeedMax = getDouble("mobs.zombie_horse.attributes.movement_speed.max", zombieHorseMovementSpeedMax);
+ zombieHorseSpawnChance = getDouble("mobs.zombie_horse.spawn-chance", zombieHorseSpawnChance);
}
public boolean zombieVillagerRidable = false;

Some files were not shown because too many files have changed in this diff Show More