Compare commits

...
Author SHA1 Message Date
Jason Penilla 39203a65e0 [ci skip] Publish PR API and dev bundles (#12672)
* Setup PR publishing

also remove the JDK matrix, it's pointless with one value and other parts of the workflow depend on a single value...

* Use PaperMC action

* Change base PR maven url

* Update action

* Update action

* Update action

* Update action

* Update action

* Re-enable javadoc...?

* Delete PR comment workflow

* Rename publish tag

* comment broken jd link

* update bot name
2025-06-16 17:35:54 -07:00
Jake Potrebic ba7fb23ddd Finish moving over to Holderable (#12646) 2025-06-10 16:29:10 -07:00
Spottedleaf 519e4224b1 Fix infinite loop in RegionFile IO
If an exception is thrown during decompress then the read process
would be started again, which of course would eventually throw in
the decompress process.
2025-06-09 02:46:34 -07:00
Jake Potrebic 95565e0f4f Add missing attribute serialization updater 2025-06-08 18:33:24 -07:00
David 320f25cb04 fix sponge-absorb deleting chest content (#12647) 2025-06-07 22:28:37 +01:00
Mart 3527ccdf2e feat: expose updateDemand and restock on Villager (#12608) 2025-06-07 12:42:11 +02:00
David Polt 03efecf0d3 Do not fire PlayerDropItemEvent for /give command 2025-06-07 12:22:48 +02:00
Shane Freeder 94f2903584 Do not blow up accessing unregistered memories from API (Fixes #12618) (#12639) 2025-06-06 22:37:52 -04:00
Warrior e87320d5f2 Fix UOE when using generateTree with pale oak (#12616) 2025-06-06 21:51:42 -04:00
Strokkur24 7ebc94c2a6 Add Registry#getTagValues (#12603) 2025-06-06 18:23:02 -07:00
Shane Freeder 4eda045b15 Backport fix for MC-296337 (Fixes #12617) (#12619) 2025-06-06 19:05:30 +01:00
Spottedleaf 2ba1675c75 Replace deprecated Thread#getId usage with Thread#threadId 2025-05-29 04:59:52 -07:00
Spottedleaf 6f315356b6 Add MCUtil#toLocation from Folia
Helper methods to convert NMS world/position to Bukkit Location
2025-05-29 04:58:00 -07:00
Jason Penilla 4765010083 Improve error messages when PluginRemapper fails to initialize (#12598) 2025-05-28 12:33:25 -07:00
40 changed files with 373 additions and 859 deletions

No files matched your search

+14 -9
View File
@@ -19,18 +19,16 @@ jobs:
# The goal of the build workflow is split into multiple requirements.
# 1. Run on pushes to same repo.
# 2. Run on PR open/reopen/syncs from repos that are not the same (PRs from the same repo are covered by 1)
# 3. Run on labeled PRs that have the build-pr-jar flag.
# 3. Run on labeled PRs that have the publish-pr flag.
if: >
(
(github.event_name == 'push')
|| (github.event_name == 'pull_request' && github.repository != github.event.pull_request.head.repo.full_name && contains(fromJSON('["opened", "reopened", "synchronize"]'), github.event.action))
|| (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'build-pr-jar')
|| (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'publish-pr')
)
runs-on: ubuntu-latest
strategy:
matrix:
java: [21]
fail-fast: true
steps:
- if: ${{ github.event_name == 'push' }}
@@ -43,10 +41,10 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: JDK ${{ matrix.java }}
- name: JDK 21
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
java-version: 21
distribution: 'zulu'
- name: Setup Gradle
@@ -73,14 +71,14 @@ jobs:
if (event_name === "push" && ref_type === "branch") {
const {data: pulls} = await github.rest.pulls.list({ owner, repo, head: `${owner}:${ref_name}`, state: "open" });
const pull = pulls.find((pr) => !!pr.labels.find((l) => l.name === "build-pr-jar"));
const pull = pulls.find((pr) => !!pr.labels.find((l) => l.name === "publish-pr"));
if (pull) {
result["pr"] = pull.number;
result["action"] = "paperclip";
core.notice(`This is a push action but to a branch with an open PR with the build paperclip label (${JSON.stringify(result)})`);
return result;
}
} else if (event_name === "pull_request" && event.pull_request.labels.find((l) => l.name === "build-pr-jar")) {
} else if (event_name === "pull_request" && event.pull_request.labels.find((l) => l.name === "publish-pr")) {
result["pr"] = event.pull_request.number;
result["action"] = "paperclip";
core.notice(`This is a pull request action with a build paperclip label (${JSON.stringify(result)})`);
@@ -102,7 +100,7 @@ jobs:
if: always()
uses: actions/upload-artifact@v4
with:
name: Test Results (${{ matrix.java }})
name: Test Results
path: |
**/build/test-results/test/TEST-*.xml
@@ -116,6 +114,13 @@ jobs:
with:
name: paper-${{ fromJSON(steps.determine.outputs.result).pr }}
path: paper-server/build/libs/paper-paperclip-*-mojmap.jar
- name: Publish Artifacts
if: fromJSON(steps.determine.outputs.result).action == 'paperclip'
uses: PaperMC/action-pr-publishing/upload@paper
with:
# TODO fallback for failing javadoc
publishing-task: ":paper-api:publishAllPublicationsTo_githubPackages_PRsRepository publishDevBundlePublicationTo_githubPackages_PRsRepository -PpublishDevBundle"
event_file:
name: "Event File"
# Only run on PRs if the source branch is on someone else's repo
-84
View File
@@ -1,84 +0,0 @@
# This workflow run on the completion of the
# build workflow but only does anything if the
# triggering workflow uploaded an artifact.
#
# Do note that it is then the trigger workflow that
# determines if this will update the PR text body. All
# this workflow does is check if an uploaded artifact
# exists and there is a PR tied to the previous workflow.
name: Comment on pull request
on:
workflow_run:
workflows: ['Build Paper']
types: [completed]
jobs:
pr_comment:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
env:
BRANCH_NAME: "${{ github.event.workflow_run.head_branch }}"
PR_OWNER: "${{ github.event.workflow_run.head_repository.owner.login }}"
PR_SHA: "${{ github.event.workflow_run.head_sha }}"
RUN_ID: "${{ github.event.workflow_run.id }}"
REPO_ID: "${{ github.event.repository.id }}"
EVENT_TYPE: "${{ github.event.workflow_run.event}}"
PULL_REQUESTS: "${{ toJSON(github.event.workflow_run.pull_requests) }}"
with:
# This snippet is public-domain, taken from
# https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml
# Modified extensively by Machine_Maker
script: |
async function updatePR(owner, repo, issue_number, purpose, body) {
const { data } = await github.rest.issues.get({ owner, repo, issue_number });
core.debug(JSON.stringify(data, null, 2));
const marker = `<!-- bot: ${purpose} -->`;
let new_body = data.body ? data.body.trim().split(marker)[0].trim() : "";
new_body += `\n${marker}\n---\n${body}`;
core.info(`Updating the text body of PR #${issue_number} in ${owner}/${repo}`);
await github.rest.issues.update({ owner, repo, issue_number, body: new_body });
}
const { owner, repo } = context.repo;
const run_id = `${process.env.RUN_ID}`;
const repo_id = `${process.env.REPO_ID}`;
let pulls = [];
const event_type = `${process.env.EVENT_TYPE}`;
if (event_type === "push") { // if push, it's from the same repo which means `pull_requests` is populated
pulls = JSON.parse(`${process.env.PULL_REQUESTS}`);
} else {
const pr_branch = `${process.env.BRANCH_NAME}`;
const pr_sha = `${process.env.PR_SHA}`;
const pr_owner = `${process.env.PR_OWNER}`;
const { data } = await github.rest.pulls.list({ owner, repo, head: `${pr_owner}:${pr_branch}`, state: "open" });
core.debug(JSON.stringify(data, null, 2));
pulls = data.filter((pr) => pr.head.sha === pr_sha && pr.labels.find((l) => l.name === "build-pr-jar"));
}
if (!pulls.length) {
return core.notice("This workflow doesn't have any pull requests!");
} else if (pulls.length > 1) {
core.info(JSON.stringify(pulls, null, 2));
return core.error("Found multiple matching PRs");
}
const pull_request = pulls[0];
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, { owner, repo, run_id });
if (!artifacts.length) {
return core.info("Skipping comment due to no artifact found");
}
const artifact = artifacts.find((art) => art.name === `paper-${pull_request.number}`);
if (!artifact) {
return core.info("Skipping comment to no matching artifact found");
}
const link = `https://nightly.link/${owner}/${repo}/actions/artifacts/${artifact.id}.zip`;
const body = `Download the paperclip jar for this pull request: [${artifact.name}.zip](${link})`;
core.info(`Adding a link to ${link}`);
await updatePR(owner, repo, pull_request.number, "paperclip-pr-build", body);
+36
View File
@@ -0,0 +1,36 @@
name: Publish PR
on:
workflow_run:
workflows: [ "Build Paper" ]
types:
- completed
permissions:
packages: write # To upload the PR
actions: write # To get information about the uploading workflow run and to delete the run artifacts
contents: write # To download the `maven-publish` artifact, and to be able to create commit comments
issues: write # To be able to create PR comments
pull-requests: write # To be able to create PR comments
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Generate an Application repository access token
id: gen_repo_token
uses: kattecon/gh-app-access-token-gen@v1
with:
app_id: 1408328
private_key: ${{ secrets.PR_PUBLISHING_GH_APP_KEY }}
repository: ${{ github.repository }}
- name: Publish PR
uses: PaperMC/action-pr-publishing@paper
env:
GITHUB_TOKEN: ${{ steps.gen_repo_token.outputs.token }}
with:
publishing-token: ${{ github.token }}
uploader-workflow-name: Build Paper
artifacts-base-path: io/papermc/paper
base-maven-url: 'https://maven-prs.papermc.io'
self-name: 'papermc-pr-publishing[bot]'
+4 -3
View File
@@ -21,12 +21,13 @@ jobs:
uses: dawidd6/action-download-artifact@v6
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts
path: test_artifacts
name: Test Results
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
commit: ${{ github.event.workflow_run.head_sha }}
event_file: artifacts/Event File/event.json
event_file: test_artifacts/Event File/event.json
event_name: ${{ github.event.workflow_run.event }}
files: "artifacts/**/*.xml"
files: "test_artifacts/**/*.xml"
comment_mode: off
+1
View File
@@ -419,6 +419,7 @@ public net.minecraft.world.entity.npc.Villager increaseMerchantCareer()V
public net.minecraft.world.entity.npc.Villager numberOfRestocksToday
public net.minecraft.world.entity.npc.Villager releaseAllPois()V
public net.minecraft.world.entity.npc.Villager setUnhappy()V
public net.minecraft.world.entity.npc.Villager updateDemand()V
public net.minecraft.world.entity.npc.WanderingTrader getWanderTarget()Lnet/minecraft/core/BlockPos;
public net.minecraft.world.entity.player.Abilities flyingSpeed
public net.minecraft.world.entity.player.Abilities walkingSpeed
+1 -1
View File
@@ -184,7 +184,7 @@ tasks.withType<Javadoc> {
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
"https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/",
"https://logging.apache.org/log4j/2.x/javadoc/log4j-api/",
// "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", // TODO: Broken
"https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3",
)
options.tags("apiNote:a:API Note:")
@@ -3,6 +3,7 @@ package io.papermc.paper.registry.set;
import io.papermc.paper.registry.TypedKey;
import java.util.Collection;
import java.util.Iterator;
import io.papermc.paper.registry.tag.TagKey;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.jetbrains.annotations.ApiStatus;
@@ -33,6 +34,7 @@ public non-sealed interface RegistryKeySet<T extends Keyed> extends Iterable<Typ
* @param registry the registry to resolve the values from (must match {@link #registryKey()})
* @return the resolved values
* @see RegistryKeySet#values()
* @see Registry#getTagValues(TagKey)
*/
@Unmodifiable Collection<T> resolve(final Registry<T> registry);
@@ -491,10 +491,27 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @throws NoSuchElementException if no tag with the given key is found
* @throws UnsupportedOperationException if this registry doesn't have or support tags
* @see #hasTag(TagKey)
* @see #getTagValues(TagKey)
*/
@ApiStatus.Experimental
Tag<T> getTag(TagKey<T> key);
/**
* Gets the named registry set (tag) for the given key and resolves it with this registry.
*
* @param key the key to get the tag for
* @return the resolved values
* @throws NoSuchElementException if no tag with the given key is found
* @throws UnsupportedOperationException if this registry doesn't have or support tags
* @see #getTag(TagKey)
* @see Tag#resolve(Registry)
*/
@ApiStatus.Experimental
default Collection<T> getTagValues(TagKey<T> key) {
Tag<T> tag = getTag(key);
return tag.resolve(this);
}
/**
* Gets all the tags in this registry.
*
@@ -391,4 +391,21 @@ public interface Villager extends AbstractVillager {
* reputation regardless of its impact and the player associated.
*/
public void clearReputations();
/**
* Updates the demand for Villager offers.
* Demand can rise and fall based on how often offers are traded.
* They can fall when an item is not traded for a while, or rise when the item is resupplied next.
* Demand is used to calculate the price of items in the Villager's offers.
* <br>
* <b>Note: Demand is stored per item and not per Villager.</b>
*/
public void updateDemand();
/**
* Resets uses of all offers for the Villager. This also internally calls {@link #updateDemand()}.
* Calling this will trigger a {@link org.bukkit.event.entity.VillagerReplenishTradeEvent} for each offer that is restocked.
* Demand is still updated even if all events are canceled.
*/
public void restock();
}
@@ -155,7 +155,7 @@ public final class RegistryEntries {
entry(Registries.VILLAGER_TYPE, VillagerType.class, Villager.Type.class),
entry(Registries.MAP_DECORATION_TYPE, MapDecorationTypes.class, MapCursor.Type.class),
entry(Registries.MENU, net.minecraft.world.inventory.MenuType.class, MenuType.class),
entry(Registries.ATTRIBUTE, Attributes.class, Attribute.class),
entry(Registries.ATTRIBUTE, Attributes.class, Attribute.class).serializationUpdater("ATTRIBUTE_RENAME"),
entry(Registries.FLUID, Fluids.class, Fluid.class),
entry(Registries.SOUND_EVENT, SoundEvents.class, Sound.class).allowDirect().apiRegistryField("SOUNDS"),
entry(Registries.DATA_COMPONENT_TYPE, DataComponents.class, DataComponentType.class, "Paper").preload(DataComponentTypes.class).apiAccessName("of")
@@ -358,7 +358,7 @@ index 88b81a5fbc88e6240f86c1e780d80eb4b601df8c..00a5ed09caa2689543bd47bcd93d5a61
import java.io.Writer;
import java.nio.file.Path;
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 156f7ddc2fdc96b762598bad2a2b21f433518dc0..ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b 100644
index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6719a16fc 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -544,6 +544,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -468,7 +468,7 @@ index bf44f6b9c8710e0c9a85d44f6217501abc98a7b1..bfd904e468bbf2cc1a5b3353d3a69ad5
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc879d602c48 100644
index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744b0434e94 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -388,6 +388,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -487,7 +487,7 @@ index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc87
// CraftBukkit end
// Paper start
@@ -403,6 +412,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -407,6 +416,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.position = Vec3.ZERO;
this.blockPosition = BlockPos.ZERO;
this.chunkPosition = ChunkPos.ZERO;
@@ -501,7 +501,7 @@ index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc87
SynchedEntityData.Builder builder = new SynchedEntityData.Builder(this);
builder.define(DATA_SHARED_FLAGS_ID, (byte)0);
builder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply());
@@ -958,6 +974,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -962,6 +978,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
if (type == MoverType.PISTON) {
@@ -512,7 +512,7 @@ index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc87
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -971,6 +991,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -975,6 +995,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stuckSpeedMultiplier = Vec3.ZERO;
this.setDeltaMovement(Vec3.ZERO);
}
@@ -527,7 +527,7 @@ index fd0cc1bf9e4425a0924ed77854907deec1a7348e..1c9e5f61d182cf60caa885135abddc87
movement = this.maybeBackOffFromEdge(movement, type);
Vec3 vec3 = this.collide(movement);
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 4123354a660f85905c8c2db1c5377201c2b8267e..7ba7a00b8dee651ca7a3cab5b64b4ae11aa66da9 100644
index 267544f50fafd914566df1c4b2327bc64d673165..3e8f4f3c3d43c6875108295187023c48eece2788 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3163,6 +3163,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -822,7 +822,7 @@ index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98a
+
}
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 1aa98e4f70627632d3e676395c28fa0ecca72f56..1f26826b2161cfeb27e5b2060e178b493e9142d9 100644
index fff4914de57dff26f66259a145d662ff5c96d840..1bb40f18b671d63719d96a58ff283767c2cfe383 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -143,6 +143,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@@ -1138,7 +1138,7 @@ index 0000000000000000000000000000000000000000..a814512fcfb85312474ae2c2c2144384
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
new file mode 100644
index 0000000000000000000000000000000000000000..1acea58838f057ab87efd103cbecb6f5aeaef393
index 0000000000000000000000000000000000000000..25bceb88f7d040034a740c18ed5a3aab50b0c72b
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -0,0 +1,1700 @@
@@ -2287,7 +2287,7 @@ index 0000000000000000000000000000000000000000..1acea58838f057ab87efd103cbecb6f5
+ LOGGER.error("Failed to decompress chunk data for task: " + this.toString(), thr);
+ }
+
+ if (compoundTag == null) {
+ if (throwable == null && compoundTag == null) {
+ // need to re-try from the start
+ this.scheduleReadIO();
+ return;
@@ -28601,7 +28601,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be231609182970 100644
index bcac0c25acb8c5176c2ca6bffbae118d83fb63f7..4057431072cd1ca159b25576969908ed30ad0868 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -28695,8 +28695,8 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
}
// Paper end - Share random for entities to make them more random
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
@@ -405,6 +361,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return this.dimensions.makeBoundingBox(x, y, z);
@@ -409,6 +365,156 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.movementThisTick.clear();
}
// Paper end
+ // Paper start - rewrite chunk system
@@ -28852,7 +28852,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
public Entity(EntityType<?> entityType, Level level) {
this.type = entityType;
@@ -1345,35 +1451,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1349,35 +1455,77 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return distance;
}
@@ -28954,7 +28954,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
}
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2616,21 +2764,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -2620,21 +2768,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean isInWall() {
@@ -29076,7 +29076,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
}
public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4078,15 +4315,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4082,15 +4319,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public Iterable<Entity> getIndirectPassengers() {
@@ -29102,7 +29102,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
}
public int countPlayerPassengers() {
@@ -4229,77 +4468,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4233,77 +4472,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(partialTick, this.yRotO, this.yRot);
}
@@ -29293,7 +29293,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4454,6 +4752,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4458,6 +4756,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -29309,7 +29309,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
if (!checkPosition(this, x, y, z)) {
return;
}
@@ -4587,6 +4894,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4591,6 +4898,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
@@ -29322,7 +29322,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) {
@@ -4597,7 +4910,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4601,7 +4914,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding();
}
@@ -29331,7 +29331,7 @@ index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be2316
this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason);
// Paper start - Folia schedulers
@@ -4631,7 +4944,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4635,7 +4948,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean shouldBeSaved() {
return (this.removalReason == null || this.removalReason.shouldSave())
&& !this.isPassenger()
@@ -8,6 +8,24 @@
int maxStackSize = itemStack.getMaxStackSize();
int i = maxStackSize * 100;
if (count > i) {
@@ -66,7 +_,7 @@
ItemStack itemStack1 = item.createItemStack(min, false);
boolean flag = serverPlayer.getInventory().add(itemStack1);
if (flag && itemStack1.isEmpty()) {
- ItemEntity itemEntity = serverPlayer.drop(itemStack, false);
+ ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (itemEntity != null) {
itemEntity.makeFakeItem();
}
@@ -84,7 +_,7 @@
);
serverPlayer.containerMenu.broadcastChanges();
} else {
- ItemEntity itemEntity = serverPlayer.drop(itemStack1, false);
+ ItemEntity itemEntity = serverPlayer.drop(itemStack1, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (itemEntity != null) {
itemEntity.setNoPickUpDelay();
itemEntity.setTarget(serverPlayer.getUUID());
@@ -95,11 +_,11 @@
if (targets.size() == 1) {
@@ -135,7 +135,7 @@
@Nullable
private BlockState inBlockState = null;
private final List<List<Entity.Movement>> movementThisTick = new ObjectArrayList<>();
@@ -259,6 +_,41 @@
@@ -259,6 +_,45 @@
private final LongSet visitedBlocks = new LongOpenHashSet();
private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector();
private CustomData customData = CustomData.EMPTY;
@@ -173,6 +173,10 @@
+ public final AABB getBoundingBoxAt(double x, double y, double z) {
+ return this.dimensions.makeBoundingBox(x, y, z);
+ }
+ // MC-296337
+ protected void clearMovementsThisTick() {
+ this.movementThisTick.clear();
+ }
+ // Paper end
public Entity(EntityType<?> entityType, Level level) {
@@ -96,6 +96,14 @@
}
}
@@ -386,6 +_,7 @@
public void applyEffectsFromBlocks() {
if (!useExperimentalMovement(this.level())) {
this.applyEffectsFromBlocks(this.position(), this.position());
+ this.clearMovementsThisTick(); // Paper - MC-296337
} else {
super.applyEffectsFromBlocks();
}
@@ -457,6 +_,15 @@
this.setDisplayOffset(compound.getIntOr("DisplayOffset", this.getDefaultDisplayOffset()));
this.flipped = compound.getBooleanOr("FlippedRotation", false);
@@ -10,7 +10,7 @@
pos,
6,
65,
@@ -63,16 +_,18 @@
@@ -63,8 +_,10 @@
if (blockPos.equals(pos)) {
return BlockPos.TraversalNodeStatus.ACCEPT;
} else {
@@ -23,8 +23,7 @@
if (!fluidState.is(FluidTags.WATER)) {
return BlockPos.TraversalNodeStatus.SKIP;
} else if (blockState.getBlock() instanceof BucketPickup bucketPickup
- && !bucketPickup.pickupBlock(null, level, blockPos, blockState).isEmpty()) {
+ && !bucketPickup.pickupBlock(null, blockList, blockPos, blockState).isEmpty()) { // CraftBukkit
@@ -72,7 +_,7 @@
return BlockPos.TraversalNodeStatus.ACCEPT;
} else {
if (blockState.getBlock() instanceof LiquidBlock) {
@@ -1,14 +1,13 @@
package io.papermc.paper.datacomponent;
import java.util.function.Function;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.util.NullOps;
import net.minecraft.util.Unit;
import org.bukkit.craftbukkit.CraftRegistry;
public record DataComponentAdapter<NMS, API>(
DataComponentType<NMS> type,
Function<API, NMS> apiToVanilla,
Function<NMS, API> vanillaToApi,
boolean codecValidation
@@ -27,11 +26,11 @@ public record DataComponentAdapter<NMS, API>(
return this.apiToVanilla == API_TO_UNIMPLEMENTED_CONVERTER;
}
public NMS toVanilla(final API value) {
public NMS toVanilla(final API value, final Holder<? extends DataComponentType<NMS>> type) {
final NMS nms = this.apiToVanilla.apply(value);
if (this.codecValidation) {
this.type.codecOrThrow().encodeStart(CraftRegistry.getMinecraftRegistry().createSerializationContext(NullOps.INSTANCE), nms).ifError(error -> {
throw new IllegalArgumentException("Failed to encode data component %s (%s)".formatted(BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(this.type), error.message()));
if (this.codecValidation && !type.value().isTransient()) {
type.value().codecOrThrow().encodeStart(CraftRegistry.getMinecraftRegistry().createSerializationContext(NullOps.INSTANCE), nms).ifError(error -> {
throw new IllegalArgumentException("Failed to encode data component %s (%s)".formatted(type.unwrapKey().orElseThrow(), error.message()));
});
}
@@ -40,10 +40,10 @@ import io.papermc.paper.datacomponent.item.PaperUseRemainder;
import io.papermc.paper.datacomponent.item.PaperWeapon;
import io.papermc.paper.datacomponent.item.PaperWritableBookContent;
import io.papermc.paper.datacomponent.item.PaperWrittenBookContent;
import io.papermc.paper.registry.PaperRegistries;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import io.papermc.paper.registry.PaperRegistries;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -147,7 +147,8 @@ public final class DataComponentAdapters {
register(DataComponents.OMINOUS_BOTTLE_AMPLIFIER, PaperOminousBottleAmplifier::new);
register(DataComponents.JUKEBOX_PLAYABLE, PaperJukeboxPlayable::new);
register(DataComponents.PROVIDES_BANNER_PATTERNS, PaperRegistries::fromNms, PaperRegistries::toNms);
register(DataComponents.RECIPES,
register(
DataComponents.RECIPES,
nms -> transformUnmodifiable(nms, PaperAdventure::asAdventureKey),
api -> transformUnmodifiable(api, key -> PaperAdventure.asVanilla(Registries.RECIPE, key))
);
@@ -164,7 +165,7 @@ public final class DataComponentAdapters {
// bees
// register(DataComponents.LOCK, PaperLockCode::new);
register(DataComponents.CONTAINER_LOOT, PaperSeededContainerLoot::new);
register(DataComponents.BREAK_SOUND, nms -> PaperAdventure.asAdventure(nms.value().location()), PaperAdventure::resolveSound);
register(DataComponents.BREAK_SOUND, nms -> PaperAdventure.asAdventure(nms.value().location()), PaperAdventure::resolveSound);
register(DataComponents.TOOLTIP_DISPLAY, PaperTooltipDisplay::new);
register(DataComponents.WEAPON, PaperWeapon::new);
register(DataComponents.BLOCKS_ATTACKS, PaperBlocksAttacks::new);
@@ -195,38 +196,42 @@ public final class DataComponentAdapters {
register(DataComponents.SHEEP_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.SHULKER_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
for (final Map.Entry<ResourceKey<DataComponentType<?>>, DataComponentType<?>> componentType : BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet()) {
if (!ADAPTERS.containsKey(componentType.getKey())) {
registerUnimplemented(componentType.getValue());
for (final ResourceKey<DataComponentType<?>> key : BuiltInRegistries.DATA_COMPONENT_TYPE.registryKeySet()) {
if (!ADAPTERS.containsKey(key)) {
registerUnimplemented(key);
}
}
}
private static <NMS> ResourceKey<DataComponentType<?>> getKey(final DataComponentType<NMS> type) {
return BuiltInRegistries.DATA_COMPONENT_TYPE.getResourceKey(type).orElseThrow();
}
public static void registerUntyped(final DataComponentType<Unit> type) {
registerInternal(type, UNIT_TO_API_CONVERTER, DataComponentAdapter.API_TO_UNIT_CONVERTER, false);
registerInternal(getKey(type), UNIT_TO_API_CONVERTER, DataComponentAdapter.API_TO_UNIT_CONVERTER, false);
}
private static <COMMON> void registerIdentity(final DataComponentType<COMMON> type) {
registerInternal(type, Function.identity(), Function.identity(), true);
registerInternal(getKey(type), Function.identity(), Function.identity(), true);
}
public static <NMS> void registerUnimplemented(final DataComponentType<NMS> type) {
registerInternal(type, UNIMPLEMENTED_TO_API_CONVERTER, DataComponentAdapter.API_TO_UNIMPLEMENTED_CONVERTER, false);
@SuppressWarnings("unchecked")
public static void registerUnimplemented(final ResourceKey<DataComponentType<?>> key) {
registerInternal(key, UNIMPLEMENTED_TO_API_CONVERTER, DataComponentAdapter.API_TO_UNIMPLEMENTED_CONVERTER, false);
}
private static <NMS, API extends Handleable<NMS>> void register(final DataComponentType<NMS> type, final Function<NMS, API> vanillaToApi) {
registerInternal(type, vanillaToApi, Handleable::getHandle, false);
registerInternal(getKey(type), vanillaToApi, Handleable::getHandle, false);
}
private static <NMS, API> void register(final DataComponentType<NMS> type, final Function<NMS, API> vanillaToApi, final Function<API, NMS> apiToVanilla) {
registerInternal(type, vanillaToApi, apiToVanilla, false);
registerInternal(getKey(type), vanillaToApi, apiToVanilla, false);
}
private static <NMS, API> void registerInternal(final DataComponentType<NMS> type, final Function<NMS, API> vanillaToApi, final Function<API, NMS> apiToVanilla, final boolean codecValidation) {
final ResourceKey<DataComponentType<?>> key = BuiltInRegistries.DATA_COMPONENT_TYPE.getResourceKey(type).orElseThrow();
private static <NMS, API> void registerInternal(final ResourceKey<DataComponentType<?>> key, final Function<NMS, API> vanillaToApi, final Function<API, NMS> apiToVanilla, final boolean codecValidation) {
if (ADAPTERS.containsKey(key)) {
throw new IllegalStateException("Duplicate adapter registration for " + key);
}
ADAPTERS.put(key, new DataComponentAdapter<>(type, apiToVanilla, vanillaToApi, codecValidation && !type.isTransient()));
ADAPTERS.put(key, new DataComponentAdapter<>(apiToVanilla, vanillaToApi, codecValidation));
}
}
@@ -1,17 +1,16 @@
package io.papermc.paper.datacomponent;
import io.papermc.paper.registry.HolderableBase;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.jspecify.annotations.Nullable;
public abstract class PaperDataComponentType<T, NMS> implements DataComponentType, Handleable<net.minecraft.core.component.DataComponentType<NMS>> {
public abstract class PaperDataComponentType<T, NMS> extends HolderableBase<net.minecraft.core.component.DataComponentType<NMS>> implements DataComponentType {
static {
DataComponentAdapters.bootstrap();
@@ -42,80 +41,64 @@ public abstract class PaperDataComponentType<T, NMS> implements DataComponentTyp
return type.getAdapter().fromVanilla(nmsValue);
}
private final NamespacedKey key;
private final net.minecraft.core.component.DataComponentType<NMS> type;
private final DataComponentAdapter<NMS, T> adapter;
public PaperDataComponentType(final NamespacedKey key, final net.minecraft.core.component.DataComponentType<NMS> type, final DataComponentAdapter<NMS, T> adapter) {
this.key = key;
this.type = type;
private PaperDataComponentType(final Holder<net.minecraft.core.component.DataComponentType<NMS>> holder, final DataComponentAdapter<NMS, T> adapter) {
super(holder);
this.adapter = adapter;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public boolean isPersistent() {
return !this.type.isTransient();
return !this.getHandle().isTransient();
}
public DataComponentAdapter<NMS, T> getAdapter() {
return this.adapter;
}
@Override
public net.minecraft.core.component.DataComponentType<NMS> getHandle() {
return this.type;
}
@SuppressWarnings("unchecked")
public static <NMS> DataComponentType of(final NamespacedKey key, final net.minecraft.core.component.DataComponentType<NMS> type) {
final DataComponentAdapter<NMS, ?> adapter = (DataComponentAdapter<NMS, ?>) DataComponentAdapters.ADAPTERS.get(BuiltInRegistries.DATA_COMPONENT_TYPE.getResourceKey(type).orElseThrow());
@SuppressWarnings({"unchecked"})
public static <NMS> DataComponentType of(final Holder<?> holder) {
final DataComponentAdapter<NMS, ?> adapter = (DataComponentAdapter<NMS, ?>) DataComponentAdapters.ADAPTERS.get(holder.unwrapKey().orElseThrow());
if (adapter == null) {
throw new IllegalArgumentException("No adapter found for " + key);
throw new IllegalArgumentException("No adapter found for " + holder);
}
if (adapter.isUnimplemented()) {
return new Unimplemented<>(key, type, adapter);
return new Unimplemented<>((Holder<net.minecraft.core.component.DataComponentType<NMS>>) holder, adapter);
} else if (adapter.isValued()) {
return new ValuedImpl<>(key, type, adapter);
return new ValuedImpl<>((Holder<net.minecraft.core.component.DataComponentType<NMS>>) holder, adapter);
} else {
return new NonValuedImpl<>(key, type, adapter);
return new NonValuedImpl<>((Holder<net.minecraft.core.component.DataComponentType<NMS>>) holder, adapter);
}
}
public static final class NonValuedImpl<T, NMS> extends PaperDataComponentType<T, NMS> implements NonValued {
NonValuedImpl(
final NamespacedKey key,
final net.minecraft.core.component.DataComponentType<NMS> type,
final Holder<net.minecraft.core.component.DataComponentType<NMS>> holder,
final DataComponentAdapter<NMS, T> adapter
) {
super(key, type, adapter);
super(holder, adapter);
}
}
public static final class ValuedImpl<T, NMS> extends PaperDataComponentType<T, NMS> implements Valued<T> {
ValuedImpl(
final NamespacedKey key,
final net.minecraft.core.component.DataComponentType<NMS> type,
final Holder<net.minecraft.core.component.DataComponentType<NMS>> holder,
final DataComponentAdapter<NMS, T> adapter
) {
super(key, type, adapter);
super(holder, adapter);
}
}
public static final class Unimplemented<T, NMS> extends PaperDataComponentType<T, NMS> {
public Unimplemented(
final NamespacedKey key,
final net.minecraft.core.component.DataComponentType<NMS> type,
final Holder<net.minecraft.core.component.DataComponentType<NMS>> holder,
final DataComponentAdapter<NMS, T> adapter
) {
super(key, type, adapter);
super(holder, adapter);
}
}
}
@@ -75,7 +75,11 @@ public final class PluginRemapper {
return null;
}
return new PluginRemapper(pluginsDir);
try {
return new PluginRemapper(pluginsDir);
} catch (final Exception e) {
throw new RuntimeException("Failed to create PluginRemapper, try deleting the '" + pluginsDir.resolve(PAPER_REMAPPED) + "' directory", e);
}
}
public void shutdown() {
@@ -8,6 +8,7 @@ import io.papermc.paper.util.MappingEnvironment;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -52,32 +53,35 @@ class RemappedPluginIndex {
try {
Files.createDirectories(this.dir);
} catch (final IOException ex) {
throw new RuntimeException(ex);
throw new UncheckedIOException(ex);
}
}
this.indexFile = dir.resolve(INDEX_FILE_NAME);
if (Files.isRegularFile(this.indexFile)) {
try {
this.state = this.readIndex();
} catch (final IOException e) {
throw new RuntimeException(e);
}
this.state = this.readIndex();
} else {
this.state = new State();
}
}
private State readIndex() throws IOException {
private State readIndex() {
final State state;
try (final BufferedReader reader = Files.newBufferedReader(this.indexFile)) {
state = GSON.fromJson(reader, State.class);
} catch (final Exception ex) {
throw new RuntimeException("Failed to read index file '" + this.indexFile + "'", ex);
}
// If mappings have changed, delete all cached files and create a new index
if (!state.mappingsHash.equals(MappingEnvironment.mappingsHash())) {
for (final String fileName : state.hashes.values()) {
Files.deleteIfExists(this.dir.resolve(fileName));
final Path path = this.dir.resolve(fileName);
try {
Files.deleteIfExists(path);
} catch (final IOException ex) {
throw new UncheckedIOException("Failed to delete no longer needed file '" + path + "'", ex);
}
}
return new State();
}
@@ -111,10 +115,11 @@ class RemappedPluginIndex {
}
iterator.remove();
final Path filePath = this.dir.resolve(fileName);
try {
Files.deleteIfExists(this.dir.resolve(fileName));
Files.deleteIfExists(filePath);
} catch (final IOException ex) {
throw new RuntimeException(ex);
throw new UncheckedIOException("Failed to delete no longer needed file '" + filePath + "'", ex);
}
}
@@ -12,11 +12,17 @@ public abstract class HolderableBase<M> implements Holderable<M> {
this.holder = holder;
}
// methods below are overridden to make final
@Override
public final Holder<M> getHolder() {
return this.holder;
}
@Override
public final M getHandle() {
return Holderable.super.getHandle();
}
@Override
public final int hashCode() {
return Holderable.super.implHashCode();
@@ -28,7 +34,7 @@ public abstract class HolderableBase<M> implements Holderable<M> {
}
@Override
public final String toString() {
public String toString() {
return Holderable.super.implToString();
}
@@ -106,7 +106,7 @@ public final class PaperRegistries {
start(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE).craft(Villager.Type.class, CraftVillager.CraftType::new).build(),
start(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE).craft(MapCursor.Type.class, CraftMapCursor.CraftType::new).build(),
start(Registries.MENU, RegistryKey.MENU).craft(MenuType.class, CraftMenuType::new).build(),
start(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE).craft(Attribute.class, CraftAttribute::new).build(),
start(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE).craft(Attribute.class, CraftAttribute::new).serializationUpdater(FieldRename.ATTRIBUTE_RENAME).build(),
start(Registries.FLUID, RegistryKey.FLUID).craft(Fluid.class, CraftFluid::new).build(),
start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new, true).build(),
start(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE).craft(DataComponentTypes.class, PaperDataComponentType::of).build(),
@@ -22,7 +22,9 @@ import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.Waitable;
@@ -150,6 +152,20 @@ public final class MCUtil {
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
}
/**
* Converts a NMS World/Vector to Bukkit Location
*/
public static Location toLocation(Level world, Vec3 pos) {
return new Location(world.getWorld(), pos.x(), pos.y(), pos.z());
}
/**
* Converts a NMS World/Vector to Bukkit Location
*/
public static Location toLocation(Level world, Vec3 pos, float yaw, float pitch) {
return new Location(world.getWorld(), pos.x(), pos.y(), pos.z(), yaw, pitch);
}
public static BlockPos toBlockPos(Position pos) {
return new BlockPos(pos.blockX(), pos.blockY(), pos.blockZ());
}
@@ -1,6 +1,7 @@
package io.papermc.paper.util;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.HolderableBase;
import java.util.Locale;
import net.minecraft.core.Holder;
import org.bukkit.Keyed;
@@ -12,14 +13,13 @@ import org.jspecify.annotations.Nullable;
@SuppressWarnings({"removal", "DeprecatedIsStillUsed"})
@Deprecated
@NullMarked
public abstract class OldEnumHolderable<A extends OldEnum<A>, M> implements Holderable<M>, OldEnum<A>, Keyed {
public abstract class OldEnumHolderable<A extends OldEnum<A>, M> extends HolderableBase<M> implements Holderable<M>, OldEnum<A>, Keyed {
private final Holder<M> holder;
private final int ordinal;
private final @Nullable String name;
protected OldEnumHolderable(final Holder<M> holder, final int ordinal) {
this.holder = holder;
super(holder);
this.ordinal = ordinal;
if (holder instanceof final Holder.Reference<M> reference) {
// For backwards compatibility, minecraft values will stile return the uppercase name without the namespace,
@@ -36,11 +36,6 @@ public abstract class OldEnumHolderable<A extends OldEnum<A>, M> implements Hold
}
}
@Override
public Holder<M> getHolder() {
return this.holder;
}
@Override
@Deprecated
public int compareTo(final A other) {
@@ -66,21 +61,6 @@ public abstract class OldEnumHolderable<A extends OldEnum<A>, M> implements Hold
Preconditions.checkState(this.holder.kind() == Holder.Kind.REFERENCE, "Cannot call method for this registry item, because it is not registered.");
}
@Override
public NamespacedKey getKey() {
return MCUtil.fromResourceKey(this.holder.unwrapKey().orElseThrow(() -> new IllegalStateException("Cannot get key for this registry item, because it is not registered.")));
}
@Override
public boolean equals(final Object obj) {
return this.implEquals(obj);
}
@Override
public int hashCode() {
return this.implHashCode();
}
@Override
public String toString() {
if (this.name != null) {
@@ -1,12 +1,12 @@
package org.bukkit.craftbukkit;
import io.papermc.paper.util.Holderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.GameEvent;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull;
public class CraftGameEvent extends GameEvent implements Handleable<net.minecraft.world.level.gameevent.GameEvent> {
public class CraftGameEvent extends GameEvent implements Holderable<net.minecraft.world.level.gameevent.GameEvent> {
public static GameEvent minecraftToBukkit(net.minecraft.world.level.gameevent.GameEvent minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.GAME_EVENT);
@@ -16,57 +16,44 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final net.minecraft.resources.ResourceKey<net.minecraft.world.level.gameevent.GameEvent> handleKey; // Paper
private final net.minecraft.world.level.gameevent.GameEvent handle;
private final Holder<net.minecraft.world.level.gameevent.GameEvent> holder;
public CraftGameEvent(NamespacedKey key, net.minecraft.world.level.gameevent.GameEvent handle) {
this.key = key;
this.handleKey = net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.GAME_EVENT, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(key)); // Paper
this.handle = handle;
public CraftGameEvent(final Holder<net.minecraft.world.level.gameevent.GameEvent> holder) {
this.holder = holder;
}
@Override
public net.minecraft.world.level.gameevent.GameEvent getHandle() {
return this.handle;
public Holder<net.minecraft.world.level.gameevent.GameEvent> getHolder() {
return this.holder;
}
@Override
public int getRange() {
return this.handle.notificationRadius();
return this.getHandle().notificationRadius();
}
@Override
public int getVibrationLevel() {
return net.minecraft.world.level.gameevent.vibrations.VibrationSystem.getGameEventFrequency(this.handleKey);
return net.minecraft.world.level.gameevent.vibrations.VibrationSystem.getGameEventFrequency(this.getHolder().unwrapKey().orElseThrow());
}
@NotNull
@Override
public NamespacedKey getKey() {
return this.key;
return Holderable.super.getKey();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftGameEvent)) {
return false;
}
return this.getKey().equals(((GameEvent) other).getKey());
return Holderable.super.implEquals(other);
}
@Override
public int hashCode() {
return this.getKey().hashCode();
return Holderable.super.implHashCode();
}
@Override
public String toString() {
return "CraftGameEvent{key=" + this.key + "}";
return Holderable.super.implToString();
}
}
@@ -1,22 +1,19 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.HolderableBase;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.contents.TranslatableContents;
import org.bukkit.JukeboxSong;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull;
public class CraftJukeboxSong implements JukeboxSong, Handleable<net.minecraft.world.item.JukeboxSong> {
public class CraftJukeboxSong extends HolderableBase<net.minecraft.world.item.JukeboxSong> implements JukeboxSong {
public static JukeboxSong minecraftToBukkit(net.minecraft.world.item.JukeboxSong minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.JUKEBOX_SONG);
}
public static JukeboxSong minecraftHolderToBukkit(Holder<net.minecraft.world.item.JukeboxSong> minecraft) {
return CraftJukeboxSong.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.JUKEBOX_SONG);
}
public static net.minecraft.world.item.JukeboxSong bukkitToMinecraft(JukeboxSong bukkit) {
@@ -24,41 +21,16 @@ public class CraftJukeboxSong implements JukeboxSong, Handleable<net.minecraft.w
}
public static Holder<net.minecraft.world.item.JukeboxSong> bukkitToMinecraftHolder(JukeboxSong bukkit) {
Preconditions.checkArgument(bukkit != null);
net.minecraft.core.Registry<net.minecraft.world.item.JukeboxSong> registry = CraftRegistry.getMinecraftRegistry(Registries.JUKEBOX_SONG);
if (registry.wrapAsHolder(CraftJukeboxSong.bukkitToMinecraft(bukkit)) instanceof Holder.Reference<net.minecraft.world.item.JukeboxSong> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own trim pattern without properly registering it.");
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.JUKEBOX_SONG);
}
private final NamespacedKey key;
private final net.minecraft.world.item.JukeboxSong handle;
public CraftJukeboxSong(NamespacedKey key, net.minecraft.world.item.JukeboxSong handle) {
this.key = key;
this.handle = handle;
public CraftJukeboxSong(final Holder<net.minecraft.world.item.JukeboxSong> holder) {
super(holder);
}
@Override
public net.minecraft.world.item.JukeboxSong getHandle() {
return this.handle;
}
@Override
@NotNull
public NamespacedKey getKey() {
return this.key;
}
@NotNull
@Override
public String getTranslationKey() {
if (!(this.handle.description().getContents() instanceof TranslatableContents)) throw new UnsupportedOperationException("Description isn't translatable!"); // Paper
return ((TranslatableContents) this.handle.description().getContents()).getKey();
if (!(this.getHandle().description().getContents() instanceof TranslatableContents)) throw new UnsupportedOperationException("Description isn't translatable!"); // Paper
return ((TranslatableContents) this.getHandle().description().getContents()).getKey();
}
}
@@ -2,6 +2,7 @@ package org.bukkit.craftbukkit.attribute;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;
@@ -54,11 +55,7 @@ final class AttributeMappings {
public static @NotNull NamespacedKey uuidToKey(final UUID uuid) {
final NamespacedKey key = ATTRIBUTE_MODIFIER_IDS.get(uuid);
if (key != null) {
return key;
} else {
return NamespacedKey.minecraft(uuid.toString());
}
return Objects.requireNonNullElseGet(key, () -> NamespacedKey.minecraft(uuid.toString()));
}
private static void add(final long msb, final long lsb, final String id) {
@@ -2,6 +2,7 @@ package org.bukkit.craftbukkit.attribute;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.util.OldEnumHolderable;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
@@ -10,10 +11,8 @@ import org.bukkit.attribute.Attribute;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.legacy.FieldRename;
import org.bukkit.craftbukkit.util.ApiVersion;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull;
public class CraftAttribute implements Attribute, Handleable<net.minecraft.world.entity.ai.attributes.Attribute> {
public class CraftAttribute extends OldEnumHolderable<Attribute, net.minecraft.world.entity.ai.attributes.Attribute> implements Attribute {
private static int count = 0;
@@ -22,7 +21,7 @@ public class CraftAttribute implements Attribute, Handleable<net.minecraft.world
}
public static Attribute minecraftHolderToBukkit(Holder<net.minecraft.world.entity.ai.attributes.Attribute> minecraft) {
return CraftAttribute.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.ATTRIBUTE);
}
public static Attribute stringToBukkit(String string) {
@@ -44,16 +43,7 @@ public class CraftAttribute implements Attribute, Handleable<net.minecraft.world
}
public static Holder<net.minecraft.world.entity.ai.attributes.Attribute> bukkitToMinecraftHolder(Attribute bukkit) {
Preconditions.checkArgument(bukkit != null);
net.minecraft.core.Registry<net.minecraft.world.entity.ai.attributes.Attribute> registry = CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE);
if (registry.wrapAsHolder(CraftAttribute.bukkitToMinecraft(bukkit)) instanceof Holder.Reference<net.minecraft.world.entity.ai.attributes.Attribute> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own sound effect with out properly registering it.");
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.ATTRIBUTE);
}
public static String bukkitToString(Attribute bukkit) {
@@ -62,85 +52,17 @@ public class CraftAttribute implements Attribute, Handleable<net.minecraft.world
return bukkit.getKey().toString();
}
private final NamespacedKey key;
private final net.minecraft.world.entity.ai.attributes.Attribute attributeBase;
private final String name;
private final int ordinal;
public CraftAttribute(NamespacedKey key, net.minecraft.world.entity.ai.attributes.Attribute attributeBase) {
this.key = key;
this.attributeBase = attributeBase;
// For backwards compatibility, minecraft values will stile return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive attribute specific values.
// Custom attributes will return the key with namespace. For a plugin this should look than like a new attribute
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftAttribute.count++;
public CraftAttribute(final Holder<net.minecraft.world.entity.ai.attributes.Attribute> holder) {
super(holder, count++);
}
@Override
public net.minecraft.world.entity.ai.attributes.Attribute getHandle() {
return this.attributeBase;
}
@NotNull
@Override
public NamespacedKey getKey() {
return this.key;
}
@NotNull
@Override
public String getTranslationKey() {
return this.attributeBase.getDescriptionId();
return this.getHandle().getDescriptionId();
}
@Override
public @NotNull String translationKey() {
return this.attributeBase.getDescriptionId();
}
@Override
public int compareTo(@NotNull Attribute attribute) {
return this.ordinal - attribute.ordinal();
}
@NotNull
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftAttribute otherAttribute)) {
return false;
}
return this.getKey().equals(otherAttribute.getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public String translationKey() {
return this.getHandle().getDescriptionId();
}
}
@@ -1,15 +1,13 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.CatVariant;
import org.bukkit.DyeColor;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Cat;
public class CraftCat extends CraftTameableAnimal implements Cat {
@@ -45,7 +43,7 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
this.getHandle().setCollarColor(net.minecraft.world.item.DyeColor.byId(color.getWoolData()));
}
public static class CraftType implements Type, Handleable<CatVariant> {
public static class CraftType extends OldEnumHolderable<Type, CatVariant> implements Type {
private static int count = 0;
public static Type minecraftToBukkit(CatVariant minecraft) {
@@ -53,7 +51,7 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
}
public static Type minecraftHolderToBukkit(Holder<CatVariant> minecraft) {
return CraftType.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.CAT_VARIANT);
}
public static CatVariant bukkitToMinecraft(Type bukkit) {
@@ -64,73 +62,8 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.CAT_VARIANT);
}
private final NamespacedKey key;
private final CatVariant catVariant;
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, CatVariant catVariant) {
this.key = key;
this.catVariant = catVariant;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftType.count++;
}
@Override
public CatVariant getHandle() {
return this.catVariant;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(Type variant) {
return this.ordinal - variant.ordinal();
}
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftType)) {
return false;
}
return this.getKey().equals(((CraftType) other).getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftType(final Holder<CatVariant> holder) {
super(holder, count++);
}
}
@@ -1,15 +1,13 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.frog.Frog;
import net.minecraft.world.entity.animal.frog.FrogVariant;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Entity;
public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
@@ -49,7 +47,7 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
this.getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant));
}
public static class CraftVariant implements Variant, Handleable<FrogVariant> {
public static class CraftVariant extends OldEnumHolderable<Variant, FrogVariant> implements Variant {
private static int count = 0;
public static Variant minecraftToBukkit(FrogVariant minecraft) {
@@ -57,7 +55,7 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
}
public static Variant minecraftHolderToBukkit(Holder<FrogVariant> minecraft) {
return CraftVariant.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.FROG_VARIANT);
}
public static FrogVariant bukkitToMinecraft(Variant bukkit) {
@@ -67,74 +65,8 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
public static Holder<FrogVariant> bukkitToMinecraftHolder(Variant bukkit) {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.FROG_VARIANT);
}
private final NamespacedKey key;
private final FrogVariant frogVariant;
private final String name;
private final int ordinal;
public CraftVariant(NamespacedKey key, FrogVariant frogVariant) {
this.key = key;
this.frogVariant = frogVariant;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive variant specific values.
// Custom variants will return the key with namespace. For a plugin this should look than like a new variant
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftVariant.count++;
}
@Override
public FrogVariant getHandle() {
return this.frogVariant;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(Variant variant) {
return this.ordinal - variant.ordinal();
}
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftVariant)) {
return false;
}
return this.getKey().equals(((Variant) other).getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftVariant(final Holder<FrogVariant> holder) {
super(holder, count++);
}
}
}
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import net.minecraft.Optionull;
@@ -905,7 +906,8 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public <T> T getMemory(MemoryKey<T> memoryKey) {
return (T) this.getHandle().getBrain().getMemory(CraftMemoryKey.bukkitToMinecraft(memoryKey)).map(CraftMemoryMapper::fromNms).orElse(null);
final Optional<?> memory = this.getHandle().getBrain().getMemoryInternal(CraftMemoryKey.bukkitToMinecraft(memoryKey));
return memory != null ? (T) memory.map(CraftMemoryMapper::fromNms).orElse(null) : null;
}
@Override
@@ -2,7 +2,7 @@ package org.bukkit.craftbukkit.entity;
import com.destroystokyo.paper.entity.villager.Reputation;
import com.google.common.base.Preconditions;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import java.util.Map;
import java.util.UUID;
import net.minecraft.core.BlockPos;
@@ -14,11 +14,9 @@ import net.minecraft.world.entity.npc.VillagerType;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Villager;
import org.bukkit.entity.ZombieVillager;
import org.bukkit.event.entity.CreatureSpawnEvent;
@@ -164,7 +162,7 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return (entityzombievillager != null) ? (ZombieVillager) entityzombievillager.getBukkitEntity() : null;
}
public static class CraftType implements Type, Handleable<VillagerType> {
public static class CraftType extends OldEnumHolderable<Type, VillagerType> implements Type {
private static int count = 0;
public static Type minecraftToBukkit(VillagerType minecraft) {
@@ -172,7 +170,7 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
}
public static Type minecraftHolderToBukkit(Holder<VillagerType> minecraft) {
return CraftType.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.VILLAGER_TYPE);
}
public static VillagerType bukkitToMinecraft(Type bukkit) {
@@ -183,77 +181,12 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.VILLAGER_TYPE);
}
private final NamespacedKey key;
private final VillagerType villagerType;
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, VillagerType villagerType) {
this.key = key;
this.villagerType = villagerType;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftType.count++;
}
@Override
public VillagerType getHandle() {
return this.villagerType;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(Type type) {
return this.ordinal - type.ordinal();
}
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftType)) {
return false;
}
return this.getKey().equals(((Type) other).getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftType(final Holder<VillagerType> holder){
super(holder, count++);
}
}
public static class CraftProfession implements Profession, Handleable<VillagerProfession> {
public static class CraftProfession extends OldEnumHolderable<Profession, VillagerProfession> implements Profession {
private static int count = 0;
public static Profession minecraftHolderToBukkit(Holder<VillagerProfession> minecraft) {
@@ -272,73 +205,8 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final VillagerProfession villagerProfession;
private final String name;
private final int ordinal;
public CraftProfession(NamespacedKey key, VillagerProfession villagerProfession) {
this.key = key;
this.villagerProfession = villagerProfession;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive profession specific values.
// Custom professions will return the key with namespace. For a plugin this should look than like a new profession
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftProfession.count++;
}
@Override
public VillagerProfession getHandle() {
return this.villagerProfession;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(Profession profession) {
return this.ordinal - profession.ordinal();
}
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftProfession)) {
return false;
}
return this.getKey().equals(((Profession) other).getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftProfession(final Holder<VillagerProfession> holder) {
super(holder, count++);
}
}
@@ -380,4 +248,14 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
public void clearReputations() {
getHandle().getGossips().gossips.clear();
}
@Override
public void updateDemand() {
getHandle().updateDemand();
}
@Override
public void restock() {
getHandle().restock();
}
}
@@ -1,15 +1,14 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.HolderableBase;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.wolf.WolfSoundVariant;
import net.minecraft.world.entity.animal.wolf.WolfVariant;
import org.bukkit.DyeColor;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Wolf;
public class CraftWolf extends CraftTameableAnimal implements Wolf {
@@ -91,14 +90,14 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
this.getHandle().setSoundVariant(CraftSoundVariant.bukkitToMinecraftHolder(soundVariant));
}
public static class CraftVariant implements Variant, Handleable<WolfVariant> {
public static class CraftVariant extends HolderableBase<WolfVariant> implements Variant {
public static Variant minecraftToBukkit(WolfVariant minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.WOLF_VARIANT);
}
public static Variant minecraftHolderToBukkit(Holder<WolfVariant> minecraft) {
return CraftVariant.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.WOLF_VARIANT);
}
public static WolfVariant bukkitToMinecraft(Variant bukkit) {
@@ -106,68 +105,22 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
}
public static Holder<WolfVariant> bukkitToMinecraftHolder(Variant bukkit) {
Preconditions.checkArgument(bukkit != null);
net.minecraft.core.Registry<WolfVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.WOLF_VARIANT);
if (registry.wrapAsHolder(CraftVariant.bukkitToMinecraft(bukkit)) instanceof Holder.Reference<WolfVariant> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own wolf variant with out properly registering it.");
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.WOLF_VARIANT);
}
private final NamespacedKey key;
private final WolfVariant variant;
public CraftVariant(NamespacedKey key, WolfVariant variant) {
this.key = key;
this.variant = variant;
}
@Override
public WolfVariant getHandle() {
return this.variant;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public String toString() {
return this.key.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftVariant otherVariant)) {
return false;
}
return this.getKey().equals(otherVariant.getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftVariant(final Holder<WolfVariant> holder) {
super(holder);
}
}
public static class CraftSoundVariant implements SoundVariant, Handleable<WolfSoundVariant> {
public static class CraftSoundVariant extends HolderableBase<WolfSoundVariant> implements SoundVariant {
public static SoundVariant minecraftToBukkit(WolfSoundVariant minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.WOLF_SOUND_VARIANT);
}
public static SoundVariant minecraftHolderToBukkit(Holder<WolfSoundVariant> minecraft) {
return CraftSoundVariant.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.WOLF_SOUND_VARIANT);
}
public static WolfSoundVariant bukkitToMinecraft(SoundVariant bukkit) {
@@ -175,57 +128,11 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
}
public static Holder<WolfSoundVariant> bukkitToMinecraftHolder(SoundVariant bukkit) {
Preconditions.checkArgument(bukkit != null);
net.minecraft.core.Registry<WolfSoundVariant> registry = CraftRegistry.getMinecraftRegistry(Registries.WOLF_SOUND_VARIANT);
if (registry.wrapAsHolder(CraftSoundVariant.bukkitToMinecraft(bukkit)) instanceof Holder.Reference<WolfSoundVariant> holder) {
return holder;
}
throw new IllegalArgumentException("No Reference holder found for " + bukkit
+ ", this can happen if a plugin creates its own wolf sound variant with out properly registering it.");
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.WOLF_SOUND_VARIANT);
}
private final NamespacedKey key;
private final WolfSoundVariant soundVariant;
public CraftSoundVariant(NamespacedKey key, WolfSoundVariant soundVariant) {
this.key = key;
this.soundVariant = soundVariant;
}
@Override
public WolfSoundVariant getHandle() {
return this.soundVariant;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public String toString() {
return this.key.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftSoundVariant otherVariant)) {
return false;
}
return this.getKey().equals(otherVariant.getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftSoundVariant(final Holder<WolfSoundVariant> holder) {
super(holder);
}
}
}
@@ -1,15 +1,14 @@
package org.bukkit.craftbukkit.generator.structure;
import com.google.common.base.Suppliers;
import java.util.function.Supplier;
import io.papermc.paper.util.Holderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
public class CraftStructure extends Structure implements Handleable<net.minecraft.world.level.levelgen.structure.Structure> {
public class CraftStructure extends Structure implements Holderable<net.minecraft.world.level.levelgen.structure.Structure> {
public static Structure minecraftToBukkit(net.minecraft.world.level.levelgen.structure.Structure minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.STRUCTURE);
@@ -19,28 +18,39 @@ public class CraftStructure extends Structure implements Handleable<net.minecraf
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final net.minecraft.world.level.levelgen.structure.Structure structure;
private final Supplier<StructureType> structureType;
private final Holder<net.minecraft.world.level.levelgen.structure.Structure> holder;
public CraftStructure(NamespacedKey key, net.minecraft.world.level.levelgen.structure.Structure structure) {
this.key = key;
this.structure = structure;
this.structureType = Suppliers.memoize(() -> CraftStructureType.minecraftToBukkit(structure.type()));
public CraftStructure(Holder<net.minecraft.world.level.levelgen.structure.Structure> holder) {
this.holder = holder;
}
@Override
public net.minecraft.world.level.levelgen.structure.Structure getHandle() {
return this.structure;
public Holder<net.minecraft.world.level.levelgen.structure.Structure> getHolder() {
return this.holder;
}
@Override
public StructureType getStructureType() {
return this.structureType.get();
return CraftStructureType.minecraftToBukkit(this.getHandle().type());
}
@Override
public NamespacedKey getKey() {
return this.key;
return Holderable.super.getKey();
}
@Override
public int hashCode() {
return Holderable.super.implHashCode();
}
@Override
public boolean equals(final Object obj) {
return Holderable.super.implEquals(obj);
}
@Override
public String toString() {
return Holderable.super.implToString();
}
}
@@ -1,12 +1,13 @@
package org.bukkit.craftbukkit.generator.structure;
import io.papermc.paper.util.Holderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.generator.structure.StructureType;
public class CraftStructureType extends StructureType implements Handleable<net.minecraft.world.level.levelgen.structure.StructureType<?>> {
public class CraftStructureType extends StructureType implements Holderable<net.minecraft.world.level.levelgen.structure.StructureType<?>> {
public static StructureType minecraftToBukkit(net.minecraft.world.level.levelgen.structure.StructureType<?> minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.STRUCTURE_TYPE);
@@ -16,21 +17,34 @@ public class CraftStructureType extends StructureType implements Handleable<net.
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final net.minecraft.world.level.levelgen.structure.StructureType<?> structureType;
private final Holder<net.minecraft.world.level.levelgen.structure.StructureType<?>> holder;
public CraftStructureType(NamespacedKey key, net.minecraft.world.level.levelgen.structure.StructureType<?> structureType) {
this.key = key;
this.structureType = structureType;
public CraftStructureType(final Holder<net.minecraft.world.level.levelgen.structure.StructureType<?>> holder) {
this.holder = holder;
}
@Override
public net.minecraft.world.level.levelgen.structure.StructureType<?> getHandle() {
return this.structureType;
public Holder<net.minecraft.world.level.levelgen.structure.StructureType<?>> getHolder() {
return this.holder;
}
@Override
public NamespacedKey getKey() {
return this.key;
return Holderable.super.getKey();
}
@Override
public int hashCode() {
return Holderable.super.implHashCode();
}
@Override
public boolean equals(final Object obj) {
return Holderable.super.implEquals(obj);
}
@Override
public String toString() {
return Holderable.super.implToString();
}
}
@@ -577,7 +577,7 @@ public final class CraftItemStack extends ItemStack {
}
private <A, V> void setDataInternal(final io.papermc.paper.datacomponent.PaperDataComponentType<A, V> type, final A value) {
this.handle.set(type.getHandle(), type.getAdapter().toVanilla(value));
this.handle.set(type.getHandle(), type.getAdapter().toVanilla(value, type.getHolder()));
}
@Override
@@ -1,17 +1,15 @@
package org.bukkit.craftbukkit.map;
import java.util.Locale;
import io.papermc.paper.util.OldEnumHolderable;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.saveddata.maps.MapDecorationType;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.map.MapCursor;
public final class CraftMapCursor {
public static final class CraftType implements MapCursor.Type, Handleable<MapDecorationType> {
public static final class CraftType extends OldEnumHolderable<MapCursor.Type, MapDecorationType> implements MapCursor.Type {
private static int count = 0;
@@ -20,7 +18,7 @@ public final class CraftMapCursor {
}
public static MapCursor.Type minecraftHolderToBukkit(Holder<MapDecorationType> minecraft) {
return CraftType.minecraftToBukkit(minecraft.value());
return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.MAP_DECORATION_TYPE);
}
public static MapDecorationType bukkitToMinecraft(MapCursor.Type bukkit) {
@@ -31,73 +29,8 @@ public final class CraftMapCursor {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.MAP_DECORATION_TYPE);
}
private final NamespacedKey key;
private final MapDecorationType mapDecorationType;
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, MapDecorationType mapDecorationType) {
this.key = key;
this.mapDecorationType = mapDecorationType;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = CraftType.count++;
}
@Override
public MapDecorationType getHandle() {
return this.mapDecorationType;
}
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public int compareTo(MapCursor.Type type) {
return this.ordinal - type.ordinal();
}
@Override
public String name() {
return this.name;
}
@Override
public int ordinal() {
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return this.name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftType)) {
return false;
}
return this.getKey().equals(((MapCursor.Type) other).getKey());
}
@Override
public int hashCode() {
return this.getKey().hashCode();
public CraftType(final Holder<MapDecorationType> holder) {
super(holder, count++);
}
@Override
@@ -86,6 +86,11 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
return this.world.getMinecraftWorld();
}
@Override
public ServerLevel getLevel() {
return this.getMinecraftWorld();
}
public void refreshTiles() {
for (CraftBlockState snapshot : this.blocks.values()) {
if (snapshot instanceof CraftBlockEntityState) {
@@ -109,7 +109,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre
logger.log(Level.SEVERE, "------------------------------");
logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper
FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information
WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger);
WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.threadId(), Integer.MAX_VALUE), logger);
logger.log(Level.SEVERE, "------------------------------");
// Paper start - Only print full dump on long timeouts