mirror of
https://github.com/PaperMC/Paper.git
synced 2026-11-04 17:00:09 -05:00
Compare commits
149
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68f8144273 | ||
|
|
f71c974030 | ||
|
|
adadeb086d | ||
|
|
df120fd8b5 | ||
|
|
7e88a0da38 | ||
|
|
f11902627b | ||
|
|
bb10cf0d5b | ||
|
|
55bebded5f | ||
|
|
f728a121f7 | ||
|
|
2401035c89 | ||
|
|
174574d871 | ||
|
|
8a170a38c6 | ||
|
|
804dd0c3f0 | ||
|
|
ff31a2c997 | ||
|
|
2e549d651c | ||
|
|
7f9c79794e | ||
|
|
9d950517d9 | ||
|
|
4f4904928f | ||
|
|
4623163095 | ||
|
|
eb9098a546 | ||
|
|
e415f5e030 | ||
|
|
e3ba7b1dc8 | ||
|
|
05c2798ec0 | ||
|
|
02378ab582 | ||
|
|
67912d0827 | ||
|
|
e8a1f8fd68 | ||
|
|
1b9bf5c8e9 | ||
|
|
325f9071f0 | ||
|
|
d86d427405 | ||
|
|
2f1ce01e87 | ||
|
|
0d9bf08a23 | ||
|
|
e65c0765c6 | ||
|
|
ac9a1b2c72 | ||
|
|
0db5c93a3d | ||
|
|
2d602d68c1 | ||
|
|
2766dd30b1 | ||
|
|
03af8b4291 | ||
|
|
45fac22871 | ||
|
|
8c0b8396d6 | ||
|
|
bc68acd741 | ||
|
|
e13b4b3d41 | ||
|
|
a90108f43c | ||
|
|
dd585fda4d | ||
|
|
1b443e0ac8 | ||
|
|
29aeb6081b | ||
|
|
3bfa02fd65 | ||
|
|
09ee222482 | ||
|
|
22c663d327 | ||
|
|
4091869eed | ||
|
|
db93f621b3 | ||
|
|
7ec11b289e | ||
|
|
683e60c092 | ||
|
|
39887673fb | ||
|
|
dba08d2f25 | ||
|
|
be4b895635 | ||
|
|
b69f87e5ac | ||
|
|
f68a55a896 | ||
|
|
a0ded751dc | ||
|
|
a48059a2d4 | ||
|
|
06b855f0d3 | ||
|
|
56cab99fbf | ||
|
|
c927bd34ab | ||
|
|
b5eb5e0bfd | ||
|
|
4738ffe335 | ||
|
|
7ff575c99b | ||
|
|
ec0cd5c5ae | ||
|
|
6e1bb67eb1 | ||
|
|
cc7ee9aebd | ||
|
|
a2d844f71e | ||
|
|
6829d9e6cb | ||
|
|
03226a5838 | ||
|
|
fbec96a8fa | ||
|
|
abe55c5242 | ||
|
|
bd9daa8fba | ||
|
|
99867f8f92 | ||
|
|
c3ec3ae0c2 | ||
|
|
1a6b058db4 | ||
|
|
821b95fb15 | ||
|
|
b2d29a4fa8 | ||
|
|
46d4834e8e | ||
|
|
e3e060d74d | ||
|
|
d57def08de | ||
|
|
21a495c94c | ||
|
|
cc7b98af63 | ||
|
|
e63aca4337 | ||
|
|
16db242251 | ||
|
|
615e915d6b | ||
|
|
8097898e6d | ||
|
|
e8750e1c00 | ||
|
|
65ba985571 | ||
|
|
b3c6bcb83c | ||
|
|
a4b87cf896 | ||
|
|
bfb089d29d | ||
|
|
4728a906ed | ||
|
|
65c408ad2d | ||
|
|
2de3a930cc | ||
|
|
780818ff42 | ||
|
|
1dbde6108f | ||
|
|
1a7b626576 | ||
|
|
6e88e469fe | ||
|
|
371c96aa68 | ||
|
|
1d254ec493 | ||
|
|
60c8e563c2 | ||
|
|
ddb45eb495 | ||
|
|
a9d038271a | ||
|
|
6bc56abc92 | ||
|
|
288d43e108 | ||
|
|
ff3655a784 | ||
|
|
1c92a6c3a4 | ||
|
|
54024d3067 | ||
|
|
3d7125903d | ||
|
|
021713af28 | ||
|
|
769bc8c2a4 | ||
|
|
977da0dbb5 | ||
|
|
af5c198def | ||
|
|
c7dd4303da | ||
|
|
be053f7afd | ||
|
|
8832a8dd7b | ||
|
|
abfdaed87a | ||
|
|
c27ca36bf1 | ||
|
|
13eb8f29ca | ||
|
|
643a11a413 | ||
|
|
e5aa18b318 | ||
|
|
f83a0bae4f | ||
|
|
bfbe49cfa9 | ||
|
|
c0f1d039bb | ||
|
|
0fdc08858f | ||
|
|
8c95c89a45 | ||
|
|
f4eb9c2e63 | ||
|
|
d3ee2cfc67 | ||
|
|
5cbb5d6fa0 | ||
|
|
640efeeabe | ||
|
|
b23b725834 | ||
|
|
f6862603dd | ||
|
|
a091961346 | ||
|
|
d289ae1dfc | ||
|
|
08ca088b5d | ||
|
|
c2f3a0311a | ||
|
|
9ae07284ad | ||
|
|
6fcbe1b7c3 | ||
|
|
426ee4eeda | ||
|
|
db3bf3cb24 | ||
|
|
6c4ddf5f84 | ||
|
|
86f056a018 | ||
|
|
04beece4d9 | ||
|
|
40af9fc7fe | ||
|
|
4461b2642b | ||
|
|
4ee96debfd | ||
|
|
644064cdd1 |
No files matched your search
@@ -14,11 +14,18 @@
|
||||
<property name="messageKey" value="annotation\.same\.line"/>
|
||||
<property name="arguments" value="^(?!(${type_use_annotations}))"/>
|
||||
</module>
|
||||
<module name="io.papermc.checkstyle.filters.BetterSuppressionSingleFilter">
|
||||
<!--Allows @deprecated on packages. Not in the javadoc spec (javadoc warns), but it is still rendered in the deprecation block and list-->
|
||||
<property name="checks" value="InappropriateJavadocBlockTagsOnPackage"/>
|
||||
<property name="messageKey" value="javadoc\.inappropriate\.tag"/>
|
||||
<property name="arguments" value="^deprecated$"/>
|
||||
</module>
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
|
||||
<!--Javadoc Comments-->
|
||||
<module name="JavadocPackage"/>
|
||||
<!--Misc-->
|
||||
<module name="LineEnding"/>
|
||||
<module name="NewlineAtEndOfFile"/>
|
||||
<!--Whitespace-->
|
||||
<module name="FileTabCharacter"/>
|
||||
@@ -38,6 +45,7 @@
|
||||
</module>
|
||||
<module name="AnnotationUseStyle"/>
|
||||
<module name="MissingDeprecated"/>
|
||||
<module name="MissingOverrideOnRecordAccessor"/>
|
||||
|
||||
<!--Block Checks-->
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
@@ -55,7 +63,9 @@
|
||||
<!--Coding-->
|
||||
<module name="AvoidDoubleBraceInitialization"/>
|
||||
<module name="AvoidNoArgumentSuperConstructorCall"/>
|
||||
<module name="ConstructorsDeclarationGrouping"/>
|
||||
<module name="ConstructorsDeclarationGrouping">
|
||||
<property name="orderByIncreasingParameterCount" value="true"/>
|
||||
</module>
|
||||
<module name="CovariantEquals"/>
|
||||
<module name="DeclarationOrder">
|
||||
<property name="ignoreConstructors" value="true"/>
|
||||
@@ -63,6 +73,7 @@
|
||||
<module name="DefaultComesLast"/>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="ExpressionOverBlockLambda"/>
|
||||
<module name="FallThrough"/>
|
||||
<!-- Use non-final variables as an identifier of old code for now -->
|
||||
<!--<module name="FinalLocalVariable">
|
||||
@@ -86,6 +97,9 @@
|
||||
<module name="UnnecessarySemicolonInTryWithResources"/>
|
||||
<module name="UnusedCatchParameterShouldBeUnnamed"/>
|
||||
<module name="UnusedLocalVariable"/>
|
||||
<module name="UnusedPrivateField"/>
|
||||
<module name="UnusedTryResourceShouldBeUnnamed"/>
|
||||
<module name="UseEnhancedSwitch"/>
|
||||
<module name="WhenShouldBeUsed"/>
|
||||
|
||||
<!--Headers--> <!--N/A-->
|
||||
@@ -114,9 +128,13 @@
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @see, @deprecated, @hidden"/>
|
||||
</module>
|
||||
<module name="InappropriateJavadocBlockTagsOnField"/>
|
||||
<module name="InappropriateJavadocBlockTagsOnPackage"/>
|
||||
<module name="InappropriateJavadocBlockTagsOnType"/>
|
||||
<module name="InvalidJavadocPosition"/>
|
||||
<module name="JavadocBlockTagLocation"/>
|
||||
<module name="JavadocContentLocation"/>
|
||||
<module name="JavadocEndCommentDelimiter"/>
|
||||
<module name="JavadocLeadingAsteriskAlign"/>
|
||||
<module name="JavadocMethod">
|
||||
<!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
@@ -124,11 +142,11 @@
|
||||
</module>
|
||||
<module name="JavadocMissingLeadingAsterisk"/>
|
||||
<module name="JavadocMissingWhitespaceAfterAsterisk"/>
|
||||
<module name="JavadocStyle"/> <!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
<module name="JavadocTagContinuationIndentation"/>
|
||||
<module name="JavadocType"/> <!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
|
||||
<module name="SummaryJavadoc"/> <!--checks all, but doesn't require. If we have a doc, it should be valid-->
|
||||
|
||||
<!--Metrics--> <!--N/A-->
|
||||
|
||||
@@ -136,12 +154,14 @@
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="AvoidEscapedUnicodeCharacters"/>
|
||||
<module name="CommentsIndentation"/>
|
||||
<module name="HexLiteralCase"/>
|
||||
<!-- Overlaps with the configured FinalLocalVariable, but is more strict -->
|
||||
<!--<module name="FinalParameters">
|
||||
<property name="tokens" value="METHOD_DEF,CTOR_DEF,LITERAL_CATCH,FOR_EACH_CLAUSE,PATTERN_VARIABLE_DEF"/>
|
||||
</module>-->
|
||||
|
||||
<module name="NoCodeInFile"/>
|
||||
<module name="NumericalPrefixesInfixesSuffixesCharacterCase"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="UpperEll"/>
|
||||
|
||||
@@ -180,6 +200,7 @@
|
||||
<!--Size Violations--> <!--N/A-->
|
||||
|
||||
<!--Whitespace-->
|
||||
<module name="ArrayBracketNoWhitespace"/>
|
||||
<module name="EmptyForInitializerPad"/>
|
||||
<module name="EmptyForIteratorPad"/>
|
||||
<module name="EmptyLineSeparator">
|
||||
@@ -197,9 +218,11 @@
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround"/>
|
||||
<module name="WhitespaceBeforeEmptyBody"/>
|
||||
|
||||
<!--Custom-->
|
||||
<module name="JavadocAlignParameterDescription"/>
|
||||
<module name="JavadocParamTagOrder"/>
|
||||
<module name="NullabilityAnnotations"/>
|
||||
<module name="RedundantNullability"/>
|
||||
<module name="UnnecessaryFullyQualifiedImport"/>
|
||||
|
||||
+13
-2
@@ -1,2 +1,13 @@
|
||||
* @PaperMC/paper-maintainers
|
||||
/.github/CODEOWNERS @PaperMC/core-team
|
||||
# default ownership
|
||||
* @papermc/paper-maintainers
|
||||
|
||||
# tooling
|
||||
/.github/workflows/ @papermc/tooling
|
||||
/gradle/ @papermc/tooling
|
||||
/paper-api/build.gradle.kts @papermc/tooling
|
||||
/paper-server/build.gradle.kts @papermc/tooling
|
||||
/build.gradle.kts @papermc/tooling
|
||||
/gradle.properties @papermc/tooling
|
||||
/settings.gradle.kts @papermc/tooling
|
||||
|
||||
/.github/CODEOWNERS @papermc/leadership-team
|
||||
@@ -5,14 +5,17 @@
|
||||
# of the PR relating to this action.
|
||||
|
||||
name: Build Paper
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- labeled
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
detect-version:
|
||||
runs-on: namespace-profile-linux-small
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
issues: read
|
||||
outputs:
|
||||
version: ${{ steps.detect.outputs.version }}
|
||||
steps:
|
||||
- id: detect
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
// Capturing Groups:
|
||||
// 1 = Brand
|
||||
// 2 = Minecraft Version
|
||||
// 3 = Build Number
|
||||
// 4 = Git Branch/Commit
|
||||
// 5 = Build Time
|
||||
const NEW_PATTERN = /This server is running ([A-Za-z0-9]+) version ([\d\.]+)-(DEV|\d+)-(.*) \((.*)\) \(Implementing API version .*\)(?: \(Git: .*\))?/;
|
||||
|
||||
// Capturing Groups:
|
||||
// 1 = Brand
|
||||
// 2 = Minecraft Version
|
||||
const OLD_PATTERN = /This server is running ([A-Za-z0-9]+) version .* \(MC: ([^\)]+)\) \(Implementing API version .*\)(?: \(Git: .*\))?/;
|
||||
|
||||
if (!context.payload.issue.body) {
|
||||
core.info("Issue body is empty; unable to detect version.");
|
||||
return;
|
||||
}
|
||||
|
||||
let version;
|
||||
|
||||
const match = context.payload.issue.body.match(NEW_PATTERN);
|
||||
if (match && match.length === 6) {
|
||||
version = match[2];
|
||||
} else {
|
||||
const oldMatch = context.payload.issue.body.match(OLD_PATTERN);
|
||||
if (oldMatch) {
|
||||
version = oldMatch[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (!version) {
|
||||
core.info("Unable to determine the Minecraft version from the issue body.");
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Detected Minecraft version: ${version}`);
|
||||
core.setOutput('version', version);
|
||||
|
||||
label-version:
|
||||
needs: detect-version
|
||||
if: needs.detect-version.outputs.version != ''
|
||||
runs-on: namespace-profile-linux-small
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const version = '${{ needs.detect-version.outputs.version }}';
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
labels: [`version: ${version}`],
|
||||
});
|
||||
|
||||
core.info(`Added version label for ${version}.`);
|
||||
|
||||
check-support:
|
||||
needs:
|
||||
- detect-version
|
||||
- label-version
|
||||
if: needs.detect-version.outputs.version != ''
|
||||
runs-on: namespace-profile-linux-small
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const version = '${{ needs.detect-version.outputs.version }}';
|
||||
|
||||
const apiUrl = `https://fill.papermc.io/v3/projects/paper/versions/${encodeURIComponent(version)}`;
|
||||
core.info(`Fetching version information from ${apiUrl}`);
|
||||
|
||||
let supportStatus;
|
||||
let supportEnd;
|
||||
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': `GitHub Actions (${context.repo.owner}/${context.repo.repo})`,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.status === 404) {
|
||||
core.info(`Fill has no information for version ${version}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
core.error(`Fill returned HTTP ${response.status}: ${response.statusText}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
supportStatus = data?.version?.support?.status;
|
||||
supportEnd = data?.version?.support?.end;
|
||||
} catch (error) {
|
||||
core.warning(`Failed to fetch support information: ${error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Fill support status for ${version}: ${supportStatus}`);
|
||||
|
||||
// Only comment for deprecated or unsupported versions.
|
||||
let comment;
|
||||
|
||||
if (supportStatus === 'UNSUPPORTED') {
|
||||
comment =
|
||||
`⚠️ **Minecraft ${version} is unsupported.**\n\n` +
|
||||
`This version is no longer supported by PaperMC. ` +
|
||||
(supportEnd
|
||||
? `Support _ended_ on ${supportEnd}. `
|
||||
: '') +
|
||||
`Please consider upgrading to a supported Minecraft version.`;
|
||||
} else if (supportStatus === 'DEPRECATED') {
|
||||
comment =
|
||||
`⚠️ **Minecraft ${version} is deprecated.**\n\n` +
|
||||
`This version is deprecated by PaperMC. ` +
|
||||
(supportEnd
|
||||
? `Support will end on ${supportEnd}. `
|
||||
: '') +
|
||||
`Please consider upgrading to a supported Minecraft version.`;
|
||||
} else {
|
||||
core.info(`${version} is supported or has an unknown status.`);
|
||||
return;
|
||||
}
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
if (supportStatus === 'UNSUPPORTED') {
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
name: 'status: needs triage',
|
||||
});
|
||||
} catch (error) {
|
||||
// ignore - missing label is not an error
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
labels: ['resolution: unsupported'],
|
||||
});
|
||||
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
state: 'closed',
|
||||
state_reason: 'not_planned',
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
name: Release 26.3
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@@ -9,16 +10,23 @@ permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: release-26.3
|
||||
cancel-in-progress: false
|
||||
group: release-26.3
|
||||
|
||||
jobs:
|
||||
release:
|
||||
# guard for manual dispatch
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
runs-on: namespace-profile-linux-default
|
||||
timeout-minutes: 30
|
||||
#env:
|
||||
# BUILD_NUMBER: ${{ github.run_number }}
|
||||
steps:
|
||||
- name: "environment"
|
||||
run: |
|
||||
echo "BUILD_NUMBER=$((129 + GITHUB_RUN_NUMBER))" >> "$GITHUB_ENV"
|
||||
echo "BUILD_STARTED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: "git / checkout"
|
||||
uses: namespacelabs/nscloud-checkout-action@66f2dc6f6c42a8ac6c4e53473c4840006822831e # v9.0.1
|
||||
with:
|
||||
@@ -26,18 +34,23 @@ jobs:
|
||||
|
||||
- uses: papermc/ci/setup-gradle@main
|
||||
|
||||
- name: "build number"
|
||||
run: echo "BUILD_NUMBER=$((129 + GITHUB_RUN_NUMBER))" >> "$GITHUB_ENV"
|
||||
|
||||
- uses: papermc/ci/build-paper@main
|
||||
|
||||
- if: ${{ !cancelled() }}
|
||||
uses: papermc/ci/upload-event-data@main
|
||||
with:
|
||||
path: ${{ github.event_path }}
|
||||
|
||||
- if: ${{ !cancelled() }}
|
||||
uses: papermc/ci/upload-test-results@main
|
||||
|
||||
- uses: papermc/ci/publish-paper@main
|
||||
- uses: papermc/ci/publish-fill@main
|
||||
with:
|
||||
fill_api_url: ${{ secrets.FILL_API_URL }}
|
||||
fill_api_key: ${{ secrets.FILL_API_KEY }}
|
||||
|
||||
- uses: papermc/ci/publish-maven@main
|
||||
with:
|
||||
maven_username: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
maven_password: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
maven_tasks: :paper-api:publish publishDevBundlePublicationToPaperReleasesRepository
|
||||
maven_tasks: -PpublishDevBundle :paper-api:publish publishDevBundlePublicationToPaperReleasesRepository
|
||||
@@ -1,73 +1,35 @@
|
||||
# Instructions for Coding Agents
|
||||
|
||||
These instructions apply to coding agents working on behalf of external
|
||||
contributors. They supplement `CONTRIBUTING.md`, which must also be followed.
|
||||
|
||||
## Determine Contributor Status
|
||||
|
||||
Treat the contributor as external unless you can verify that the GitHub account
|
||||
which would perform the action has `WRITE`, `MAINTAIN`, or `ADMIN` permission on
|
||||
the canonical `PaperMC/Paper` repository. Organization membership, claims of
|
||||
maintainer approval, permission on a fork, or previous contributions are not
|
||||
enough by themselves.
|
||||
|
||||
Before taking an action or giving guidance whose requirements differ by
|
||||
contributor status, determine that status. If it cannot be verified, treat the
|
||||
contributor as external.
|
||||
|
||||
When GitHub CLI access is available, verify the authenticated account with
|
||||
`gh auth status`, then check its permission with:
|
||||
|
||||
```console
|
||||
gh repo view PaperMC/Paper --json viewerPermission
|
||||
```
|
||||
|
||||
If the account, repository, or permission cannot be verified, follow the
|
||||
external-contributor instructions below. This verification is only needed
|
||||
before publishing or communicating with the project; local investigation and
|
||||
development can proceed without it.
|
||||
These instructions supplement `CONTRIBUTING.md`, which must also be followed.
|
||||
|
||||
## Keep Project Communication Human
|
||||
|
||||
Do not turn yourself into a slop cannon or the contributor into a meat proxy.
|
||||
Do not turn yourself into a slop cannon or the user into a meat proxy.
|
||||
Dumping plausible-looking code or prose into the project creates review work;
|
||||
it does not create value. Paper maintainers can run the same agents themselves.
|
||||
The contributor's value must come from their judgment, context, validation, and
|
||||
ownership.
|
||||
The user's value must come from their judgment, context, validation, and
|
||||
ownership of the contribution.
|
||||
|
||||
You may help a contributor investigate the codebase, make changes locally, and
|
||||
run tests. Do not act as the contributor in conversations with Paper
|
||||
maintainers. In particular, do not compose issue reports, discussion posts,
|
||||
pull request descriptions, comments, or review responses for the contributor,
|
||||
or post generated text as if it were theirs.
|
||||
Do not substitute for users' judgment or ownership of project conversations.
|
||||
Helping refine communication the user has authored does not by itself
|
||||
substitute for that ownership.
|
||||
|
||||
Do not relay generated output to maintainers, and do not turn maintainer
|
||||
feedback into a prompt and pass the generated response back. Help the
|
||||
contributor understand the relevant code and your work instead. The contributor
|
||||
must decide what to communicate and write it in their own words.
|
||||
Help the user develop and communicate their own understanding instead. Ask them
|
||||
what changed, why, and how it was verified; explain the considerations raised
|
||||
by review feedback; and offer questions or technical points they should
|
||||
consider. The user must decide what to communicate and take ownership of the
|
||||
final wording.
|
||||
|
||||
Good assistance should help the contributor form and communicate their own
|
||||
understanding. Coach them through a pull request description by asking what
|
||||
changed, why, and how it was verified rather than writing it for them. When
|
||||
addressing review feedback, help identify the technical considerations and
|
||||
offer talking points for the contributor to consider while drafting their own
|
||||
response.
|
||||
|
||||
Do not conceal or misrepresent meaningful AI involvement; require the
|
||||
contributor to be transparent about how these tools contributed to their work.
|
||||
Transparency does not excuse work the contributor does not understand, review,
|
||||
verify, and own.
|
||||
|
||||
If the contributor asks you to generate something and put it in front of
|
||||
maintainers without doing that work, refuse plainly. Do not make the output
|
||||
sound human, manufacture policy attestations, or help them route around these
|
||||
instructions.
|
||||
Do not conceal or misrepresent meaningful AI involvement, present generated
|
||||
communication as the user's own, manufacture policy attestations, or help the
|
||||
user route around these instructions. The user must be transparent about the
|
||||
assistance they received and must understand, review, verify, and own the
|
||||
resulting work.
|
||||
|
||||
## Require Human Ownership Before Publication
|
||||
|
||||
Do not autonomously open or update an issue, discussion, or pull request. Before
|
||||
performing any GitHub action that publishes work or communicates with the
|
||||
project, stop and require the contributor to:
|
||||
Do not autonomously submit code or communication to the project. Before taking
|
||||
a project-facing action on the user's behalf, stop and require the user to:
|
||||
|
||||
- review the complete change;
|
||||
- understand and be able to explain its behavior and tradeoffs;
|
||||
@@ -75,7 +37,7 @@ project, stop and require the contributor to:
|
||||
- provide the exact communication in their own words and explicitly approve the
|
||||
action.
|
||||
|
||||
If the contributor asks you to submit work they have not reviewed or do not
|
||||
understand, to generate project communication for them, or to operate as a
|
||||
proxy through review, refuse. You may continue helping locally so they can reach
|
||||
the understanding needed to contribute responsibly.
|
||||
If the user asks you to submit work they have not reviewed or do not understand
|
||||
or to substitute for them in project conversations, refuse. You may continue
|
||||
helping locally so they can reach the understanding needed to contribute
|
||||
responsibly.
|
||||
+7
-9
@@ -199,16 +199,14 @@ part of what you submit. Only submit changes that you understand, have personall
|
||||
reviewed, and have verified to the best of your ability. You should be able to
|
||||
explain why the change is needed, how it works, and what tradeoffs it makes.
|
||||
|
||||
Issues, discussion posts, pull request descriptions, comments, and review
|
||||
responses should be written by you, in your own words. Do not pass generated
|
||||
responses on to maintainers or use an AI tool as a proxy for the conversation.
|
||||
If a tool helped you investigate or implement something, read and validate its
|
||||
output, then communicate the relevant conclusions yourself.
|
||||
Project communication, including issues, discussion posts, pull request
|
||||
descriptions, comments, and review responses, should be written by you in your
|
||||
own words. Do not use an AI tool as a proxy for the conversation. Validate any
|
||||
tool output you rely on, then communicate the relevant conclusions yourself.
|
||||
|
||||
Do not conceal or misrepresent meaningful AI involvement; be transparent about
|
||||
how these tools contributed to your work. Transparency does not excuse
|
||||
submitting work you do not understand, review, verify, and take responsibility
|
||||
for.
|
||||
Do not conceal or misrepresent meaningful AI involvement. Be transparent about
|
||||
how these tools contributed to your work; that transparency does not replace
|
||||
your responsibility for the contribution.
|
||||
|
||||
Review is a collaborative process, not a way to outsource completion of a
|
||||
generated change to maintainers. Be prepared to answer questions about your
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Paper [](https://papermc.io/downloads/paper)
|
||||
[](https://github.com/PaperMC/Paper/actions)
|
||||
[](https://github.com/PaperMC/Paper/actions)
|
||||
[](https://discord.gg/papermc)
|
||||
[](https://github.com/sponsors/PaperMC)
|
||||
[](https://opencollective.com/papermc)
|
||||
@@ -91,6 +91,8 @@ You can find our collective [here](https://opencollective.com/papermc), or you c
|
||||
Special Thanks To:
|
||||
-------------
|
||||
|
||||
[](https://namespace.so/github-actions/?utm_source=oss&utm_campaign=papermc)
|
||||
|
||||
[](https://www.yourkit.com/)
|
||||
|
||||
[YourKit](https://www.yourkit.com/), makers of the outstanding java profiler, support open source projects of all kinds with their full featured [Java](https://www.yourkit.com/java/profiler) and [.NET](https://www.yourkit.com/.net/profiler) application profilers. We thank them for granting Paper an OSS license so that we can make our software the best it can be.
|
||||
|
||||
@@ -5,6 +5,7 @@ private-f net.minecraft.server.MinecraftServer connection
|
||||
private-f net.minecraft.server.MinecraftServer levels
|
||||
private-f net.minecraft.world.item.ItemStack components
|
||||
private-f net.minecraft.world.item.ItemStack item
|
||||
private-f net.minecraft.world.item.crafting.RecipeManager learnableRecipes
|
||||
private-f net.minecraft.world.level.block.entity.BeehiveBlockEntity stored
|
||||
protected net.minecraft.world.entity.LivingEntity skipDropExperience
|
||||
protected net.minecraft.world.level.Level thread
|
||||
@@ -24,6 +25,7 @@ public net.minecraft.network.Connection channel
|
||||
public net.minecraft.network.chat.contents.TranslatableContents PRIMITIVE_ARG_CODEC
|
||||
public net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket <init>(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V
|
||||
public net.minecraft.network.syncher.SynchedEntityData getItem(Lnet/minecraft/network/syncher/EntityDataAccessor;)Lnet/minecraft/network/syncher/SynchedEntityData$DataItem;
|
||||
public net.minecraft.resources.RegistryOps <init>(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/resources/RegistryOps$RegistryInfoLookup;)V
|
||||
public net.minecraft.resources.RegistryOps lookupProvider
|
||||
public net.minecraft.resources.RegistryOps$HolderLookupAdapter
|
||||
public net.minecraft.server.Main forceUpgrade(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lnet/minecraft/core/RegistryAccess;Z)V
|
||||
@@ -166,6 +168,8 @@ public net.minecraft.world.entity.Display$TextDisplay setText(Lnet/minecraft/net
|
||||
public net.minecraft.world.entity.Display$TextDisplay setTextOpacity(B)V
|
||||
public net.minecraft.world.entity.Entity DATA_TICKS_FROZEN
|
||||
public net.minecraft.world.entity.Entity FLAG_INVISIBLE
|
||||
public net.minecraft.world.entity.Entity getAirDrag()F
|
||||
public net.minecraft.world.entity.Entity getDefaultGravity()D
|
||||
public net.minecraft.world.entity.Entity getEncodeId()Ljava/lang/String;
|
||||
public net.minecraft.world.entity.Entity getFireImmuneTicks()I
|
||||
public net.minecraft.world.entity.Entity getSharedFlag(I)Z
|
||||
@@ -392,6 +396,7 @@ public net.minecraft.world.entity.npc.villager.Villager updateDemand()V
|
||||
public net.minecraft.world.entity.npc.villager.Villager updateSpecialPrices(Lnet/minecraft/world/entity/player/Player;)V
|
||||
public net.minecraft.world.entity.npc.wanderingtrader.WanderingTrader getWanderTarget()Lnet/minecraft/core/BlockPos;
|
||||
public net.minecraft.world.entity.player.Inventory equipment
|
||||
public net.minecraft.world.entity.player.Player canCriticalAttack(Lnet/minecraft/world/entity/Entity;)Z
|
||||
public net.minecraft.world.entity.player.Player closeContainer()V
|
||||
public net.minecraft.world.entity.player.Player enchantmentSeed
|
||||
public net.minecraft.world.entity.player.Player hurtDir
|
||||
@@ -472,8 +477,10 @@ public net.minecraft.world.inventory.AbstractMountInventoryMenu mount
|
||||
public net.minecraft.world.inventory.AnvilMenu cost
|
||||
public net.minecraft.world.inventory.AnvilMenu itemName
|
||||
public net.minecraft.world.inventory.AnvilMenu repairItemCountCost
|
||||
public net.minecraft.world.inventory.BrewingStandMenu DATA_COUNT
|
||||
public net.minecraft.world.inventory.BrewingStandMenu brewingStandData
|
||||
public net.minecraft.world.inventory.CraftingMenu access
|
||||
public net.minecraft.world.inventory.LecternMenu DATA_COUNT
|
||||
public net.minecraft.world.inventory.MerchantContainer selectionHint
|
||||
public net.minecraft.world.item.AdventureModePredicate predicates
|
||||
public net.minecraft.world.item.CrossbowItem FIREWORK_POWER
|
||||
@@ -578,6 +585,7 @@ public net.minecraft.world.level.block.entity.LecternBlockEntity bookAccess
|
||||
public net.minecraft.world.level.block.entity.LecternBlockEntity setPage(I)V
|
||||
public net.minecraft.world.level.block.entity.SculkCatalystBlockEntity$CatalystListener bloom(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/util/RandomSource;)V
|
||||
public net.minecraft.world.level.block.entity.SculkShriekerBlockEntity warningLevel
|
||||
public net.minecraft.world.level.block.entity.SignBlockEntity allowOpFeatures
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity customName
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity noteBlockSound
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity owner
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ mcVersion=26.3
|
||||
# This is the current API version for use in (paper-)plugin.yml files
|
||||
# During snapshot cycles this should be the anticipated version of the release target
|
||||
apiVersion=26.3
|
||||
channel=ALPHA
|
||||
channel=STABLE
|
||||
|
||||
# Set to true while updating Minecraft version
|
||||
updatingMinecraft=false
|
||||
|
||||
@@ -234,7 +234,8 @@ public class MaterialTags {
|
||||
* Covers all music disc items.
|
||||
*/
|
||||
public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs"))
|
||||
.startsWith("MUSIC_DISC_").lock();
|
||||
.startsWith("MUSIC_DISC_")
|
||||
.ensureSize("MUSIC_DISCS", 22).lock();
|
||||
|
||||
/**
|
||||
* Covers all ores.
|
||||
|
||||
+16
-4
@@ -1,6 +1,8 @@
|
||||
package com.destroystokyo.paper.event.player;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@@ -41,10 +43,10 @@ public class PlayerConnectionCloseEvent extends Event {
|
||||
|
||||
private final UUID playerUniqueId;
|
||||
private final String playerName;
|
||||
private final InetAddress ipAddress;
|
||||
private final SocketAddress ipAddress;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public PlayerConnectionCloseEvent(final UUID playerUniqueId, final String playerName, final InetAddress ipAddress, final boolean async) {
|
||||
public PlayerConnectionCloseEvent(final UUID playerUniqueId, final String playerName, final SocketAddress ipAddress, final boolean async) {
|
||||
super(async);
|
||||
this.playerUniqueId = playerUniqueId;
|
||||
this.playerName = playerName;
|
||||
@@ -66,10 +68,20 @@ public class PlayerConnectionCloseEvent extends Event {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player's IP address.
|
||||
* Returns the player's socket address.
|
||||
*/
|
||||
public SocketAddress getSocketAddress() {
|
||||
return this.ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player's IP address, or the loopback address if the player
|
||||
* is connecting through a Unix domain socket and the proxy has not
|
||||
* forwarded the player's IP address yet.
|
||||
*/
|
||||
public InetAddress getIpAddress() {
|
||||
return this.ipAddress;
|
||||
if (this.ipAddress instanceof InetSocketAddress inet) return inet.getAddress();
|
||||
return InetAddress.getLoopbackAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class PaperServerListPingEvent extends ServerListPingEvent implements Can
|
||||
@ApiStatus.Internal
|
||||
public PaperServerListPingEvent(@NotNull StatusClient client, @NotNull net.kyori.adventure.text.Component motd, int numPlayers, int maxPlayers,
|
||||
@NotNull String version, int protocolVersion, @Nullable CachedServerIcon favicon) {
|
||||
super("", client.getAddress().getAddress(), motd, numPlayers, maxPlayers);
|
||||
super("", client.getSocketAddress(), motd, numPlayers, maxPlayers);
|
||||
this.client = client;
|
||||
this.numPlayers = numPlayers;
|
||||
this.version = version;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.destroystokyo.paper.network;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -15,6 +16,15 @@ public interface NetworkClient {
|
||||
*
|
||||
* @return The client's socket address
|
||||
*/
|
||||
SocketAddress getSocketAddress();
|
||||
|
||||
/**
|
||||
* Returns an instance of {@link InetSocketAddress} associated with the
|
||||
* client's socket address.
|
||||
*
|
||||
* @return The client's {@link InetSocketAddress}, or the loopback address
|
||||
* if this is a Unix domain socket connection
|
||||
*/
|
||||
InetSocketAddress getAddress();
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.destroystokyo.paper.util.VersionFetcher;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.datacomponent.item.ResolvableProfile;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.persistence.PersistentDataKey;
|
||||
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||
import io.papermc.paper.world.damagesource.CombatEntry;
|
||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||
@@ -13,6 +14,7 @@ import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.flattener.ComponentFlattener;
|
||||
import net.kyori.adventure.util.Services;
|
||||
@@ -25,12 +27,14 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.damage.DamageEffect;
|
||||
import org.bukkit.damage.DamageSource;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.bukkit.enchantments.EnchantmentOffer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Pose;
|
||||
import org.bukkit.entity.SpawnCategory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -69,14 +73,15 @@ public interface InternalAPIBridge {
|
||||
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
|
||||
|
||||
/**
|
||||
* Causes this predicate to be considered restricted.
|
||||
* Applying this to a command node prevents this command from being executed from an
|
||||
* unattended context, such as click events.
|
||||
* Allows overriding default restricted check.
|
||||
* Applying this to a command node forcefully prevents or permits this command to be
|
||||
* executed from an unattended context, such as click events.
|
||||
*
|
||||
* @param predicate wrapped predicate
|
||||
* @param predicate wrapped predicate
|
||||
* @param restricted restricted status of the predicate
|
||||
* @return wrapped predicate
|
||||
*/
|
||||
Predicate<CommandSourceStack> restricted(Predicate<CommandSourceStack> predicate);
|
||||
Predicate<CommandSourceStack> restricted(Predicate<CommandSourceStack> predicate, boolean restricted);
|
||||
|
||||
ResolvableProfile defaultMannequinProfile();
|
||||
|
||||
@@ -121,4 +126,8 @@ public interface InternalAPIBridge {
|
||||
Component resolveWithContext(Component component, @Nullable CommandSender context, @Nullable Entity scoreboardSubject, boolean bypassPermissions) throws IOException;
|
||||
|
||||
ComponentFlattener componentFlattener();
|
||||
|
||||
<C> PersistentDataKey<C> createPersistentDataKey(Key key, PersistentDataType<?, C> type);
|
||||
|
||||
@Nullable EnchantmentOffer[] rollEnchantmentOffers(ItemStack targetStack, int seed, int bookshelfCount, int offerAmount);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package io.papermc.paper.block.pot;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.data.DecoratedPotPatternRegistryEntry;
|
||||
import org.bukkit.Keyed;
|
||||
|
||||
/**
|
||||
* A pot pattern on a decorated pot.
|
||||
*/
|
||||
public interface PotPatternType extends Keyed {
|
||||
public interface PotPatternType extends RegistryElement.Buildable<PotPatternType, DecoratedPotPatternRegistryEntry, DecoratedPotPatternRegistryEntry.Builder>, Keyed {
|
||||
}
|
||||
@@ -26,12 +26,12 @@ public interface ChatRenderer {
|
||||
Component render(Player source, Component sourceDisplayName, Component message, Audience viewer);
|
||||
|
||||
/**
|
||||
* Create a new instance of the default {@link ChatRenderer}.
|
||||
* Gets the default {@link ChatRenderer}.
|
||||
*
|
||||
* @return a new {@link ChatRenderer}
|
||||
* @return the default {@link ChatRenderer}
|
||||
*/
|
||||
static ChatRenderer defaultRenderer() {
|
||||
return new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message));
|
||||
return ViewerUnawareImpl.Default.INSTANCE;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
@@ -5,13 +5,11 @@ import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@NullMarked
|
||||
sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default {
|
||||
private final ViewerUnaware unaware;
|
||||
private @Nullable Component message;
|
||||
|
||||
ViewerUnawareImpl(final ViewerUnaware unaware) {
|
||||
this.unaware = unaware;
|
||||
@@ -24,13 +22,12 @@ sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnawa
|
||||
|
||||
@Override
|
||||
public Component render(final Player source, final Component sourceDisplayName, final Component message) {
|
||||
if (this.message == null) {
|
||||
this.message = this.unaware.render(source, sourceDisplayName, message);
|
||||
}
|
||||
return this.message;
|
||||
return this.unaware.render(source, sourceDisplayName, message);
|
||||
}
|
||||
|
||||
static final class Default extends ViewerUnawareImpl implements ChatRenderer.Default {
|
||||
static final ViewerUnawareImpl.Default INSTANCE = new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message));
|
||||
|
||||
Default(final ViewerUnaware unaware) {
|
||||
super(unaware);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.papermc.paper.command.brigadier;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -20,7 +21,7 @@ public interface BasicCommand {
|
||||
* @param args the arguments of the command ignoring repeated spaces
|
||||
*/
|
||||
@ApiStatus.OverrideOnly
|
||||
void execute(CommandSourceStack commandSourceStack, String[] args);
|
||||
void execute(CommandSourceStack commandSourceStack, String[] args) throws CommandSyntaxException;
|
||||
|
||||
/**
|
||||
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package io.papermc.paper.command.brigadier;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.brigadier.RedirectModifier;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import net.kyori.adventure.pointer.Pointered;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.bukkit.GameRules;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -81,4 +87,123 @@ public interface CommandSourceStack {
|
||||
* @see com.mojang.brigadier.builder.ArgumentBuilder#fork(CommandNode, RedirectModifier)
|
||||
*/
|
||||
CommandSourceStack withExecutor(Entity executor);
|
||||
|
||||
/**
|
||||
* Sends a system message to the {@link #getExecutor()} if it is a {@link Player},
|
||||
* otherwise sends a system message to the {@link #getSender()}.
|
||||
*
|
||||
* @param message the message to send
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
void sendReply(ComponentLike message);
|
||||
|
||||
/**
|
||||
* Sends a system message with the MiniMessage format to the {@link #getExecutor()}
|
||||
* if it is a {@link Player}, otherwise sends it to the {@link #getSender()}.
|
||||
*
|
||||
* <p>See <a href="https://docs.papermc.io/adventure/minimessage/">MiniMessage docs</a> and
|
||||
* <a href="https://docs.papermc.io/adventure/minimessage/dynamic-replacements/">MiniMessage Placeholders docs</a>
|
||||
* for more information on the format.</p>
|
||||
*
|
||||
* <p>This method provides the target of the system message as a {@link net.kyori.adventure.pointer.Pointered}
|
||||
* to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.</p>
|
||||
*
|
||||
* @param message the MiniMessage message to send
|
||||
* @param resolvers resolvers to use
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
default void sendRichReply(final String message, final TagResolver... resolvers) {
|
||||
Preconditions.checkArgument(message != null, "message cannot be null.");
|
||||
this.sendReply(MiniMessage.miniMessage().deserialize(
|
||||
message,
|
||||
this.getExecutor() instanceof final Player player ? player : this.getSender(),
|
||||
resolvers
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution
|
||||
* according to vanilla semantics.
|
||||
*
|
||||
* <p>This currently includes checking for environments with suppressed output,
|
||||
* {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.</p>
|
||||
*
|
||||
* @param message the message to send
|
||||
* @param allowInformingAdmins whether admins and console may be informed of this success
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
void sendSuccess(ComponentLike message, boolean allowInformingAdmins);
|
||||
|
||||
/**
|
||||
* Sends a system message to the {@link #getSender()}, admins, and console indicating successful command execution
|
||||
* according to vanilla semantics. This method informs admins and the console of this success.
|
||||
*
|
||||
* <p>This currently includes checking for environments with suppressed output,
|
||||
* {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.</p>
|
||||
*
|
||||
* @param message the message to send
|
||||
* @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
default void sendSuccess(final ComponentLike message) {
|
||||
this.sendSuccess(message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a system message with the MiniMessage format to the {@link #getSender()}, admins, and console indicating
|
||||
* successful command execution according to vanilla semantics. This method informs admins and the console of
|
||||
* this success.
|
||||
*
|
||||
* <p>This currently includes checking for environments with suppressed output,
|
||||
* {@link GameRules#SEND_COMMAND_FEEDBACK}, and {@link GameRules#LOG_ADMIN_COMMANDS}.</p>
|
||||
*
|
||||
* <p>See <a href="https://docs.papermc.io/adventure/minimessage/">MiniMessage docs</a> and
|
||||
* <a href="https://docs.papermc.io/adventure/minimessage/dynamic-replacements/">MiniMessage Placeholders docs</a>
|
||||
* for more information on the format.</p>
|
||||
*
|
||||
* <p>This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered}
|
||||
* to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.</p>
|
||||
*
|
||||
* @param message the MiniMessage message to send
|
||||
* @param resolvers resolvers to use
|
||||
* @see #sendSuccess(ComponentLike, boolean) to disable if admins and console should be informed
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
default void sendRichSuccess(final String message, final TagResolver... resolvers) {
|
||||
Preconditions.checkArgument(message != null, "message cannot be null.");
|
||||
this.sendSuccess(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a system message indicating a failed command execution to the {@link #getSender()}.
|
||||
* Does not apply red styling to the message as vanilla does to allow for custom failure message styling.
|
||||
*
|
||||
* <p>Respects vanilla semantics for accepting failure output and suppressed output environments.</p>
|
||||
*
|
||||
* @param message the message to send
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
void sendFailure(ComponentLike message);
|
||||
|
||||
/**
|
||||
* Sends a system message with the MiniMessage format indicating a failed command execution to the{@link #getSender()}.
|
||||
* Does not apply red styling to the message as vanilla does to allow for custom failure message styling.
|
||||
*
|
||||
* <p>Respects vanilla semantics for accepting failure output and suppressed output environments.</p>
|
||||
*
|
||||
* <p>See <a href="https://docs.papermc.io/adventure/minimessage/">MiniMessage docs</a> and
|
||||
* <a href="https://docs.papermc.io/adventure/minimessage/dynamic-replacements/">MiniMessage Placeholders docs</a>
|
||||
* for more information on the format.</p>
|
||||
*
|
||||
* <p>This method provides the {@link CommandSender} of this command as a {@link net.kyori.adventure.pointer.Pointered}
|
||||
* to the MiniMessage {@link MiniMessage#deserialize(String, Pointered, TagResolver...)} method.</p>
|
||||
*
|
||||
* @param message the MiniMessage message to send
|
||||
* @param resolvers resolvers to use
|
||||
* @throws IllegalArgumentException if the message is null
|
||||
*/
|
||||
default void sendRichFailure(final String message, final TagResolver... resolvers) {
|
||||
Preconditions.checkArgument(message != null, "message cannot be null.");
|
||||
this.sendFailure(MiniMessage.miniMessage().deserialize(message, this.getSender(), resolvers));
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,23 @@ public interface Commands extends Registrar {
|
||||
* @return a new predicate with restricted execution behavior
|
||||
*/
|
||||
static Predicate<CommandSourceStack> restricted(final Predicate<CommandSourceStack> predicate) {
|
||||
return InternalAPIBridge.get().restricted(predicate);
|
||||
return InternalAPIBridge.get().restricted(predicate, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unrestricted {@link Predicate} that wraps the given predicate.
|
||||
* <p>
|
||||
* A restricted predicate prevents execution in unattended contexts, such as from chat click events.
|
||||
* Unrestricting prevents the warning shown on the client before executing the command.
|
||||
* <p>
|
||||
* This is used by vanilla to prevent invocation of sensitive commands (like op) from
|
||||
* players without their knowledge.
|
||||
*
|
||||
* @param predicate the original predicate to wrap
|
||||
* @return a new predicate with unrestricted execution behavior
|
||||
*/
|
||||
static Predicate<CommandSourceStack> unrestricted(final Predicate<CommandSourceStack> predicate) {
|
||||
return InternalAPIBridge.get().restricted(predicate, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,6 +41,8 @@ public interface PlayerConnection {
|
||||
/**
|
||||
* Gets the real client address of the player. If the connection is behind a proxy,
|
||||
* this will be the actual player’s IP address extracted from the proxy handshake.
|
||||
* If the player is connecting through a Unix domain socket and the proxy has not
|
||||
* forwarded the player's IP address yet, this will be the loopback address.
|
||||
*
|
||||
* @return the client {@link InetSocketAddress}
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package io.papermc.paper.datacomponent;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
@ApiStatus.NonExtendable
|
||||
public interface DataComponentType extends Keyed {
|
||||
public interface DataComponentType extends RegistryElement<DataComponentType>, Keyed {
|
||||
|
||||
/**
|
||||
* Checks if this data component type is persistent, or
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.bukkit.DyeColor;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.MusicInstrument;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.banner.PatternType;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.bukkit.entity.Axolotl;
|
||||
@@ -365,7 +366,7 @@ public final class DataComponentTypes {
|
||||
* Holds the unresolved loot table and seed of a container-like block.
|
||||
*/
|
||||
public static final DataComponentType.Valued<SeededContainerLoot> CONTAINER_LOOT = valued("container_loot");
|
||||
public static final DataComponentType.Valued<Key> BREAK_SOUND = valued("break_sound");
|
||||
public static final DataComponentType.Valued<Sound> BREAK_SOUND = valued("break_sound");
|
||||
public static final DataComponentType.Valued<MobVisibility> MOB_VISIBILITY = valued("mob_visibility");
|
||||
public static final DataComponentType.Valued<Villager.Type> VILLAGER_VARIANT = valued("villager/variant");
|
||||
public static final DataComponentType.Valued<Wolf.Variant> WOLF_VARIANT = valued("wolf/variant");
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.papermc.paper.datacomponent.item.blocksattacks.ItemDamageFunction;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.damage.DamageType;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -68,20 +69,20 @@ public interface BlocksAttacks {
|
||||
@Nullable RegistryKeySet<DamageType> bypassedBy();
|
||||
|
||||
/**
|
||||
* Gets the key sound to play when an attack is successfully blocked.
|
||||
* Gets the sound to play when an attack is successfully blocked.
|
||||
*
|
||||
* @return a key of the sound
|
||||
* @return the sound
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@Nullable Key blockSound();
|
||||
@Nullable Sound blockSound();
|
||||
|
||||
/**
|
||||
* Gets the key sound to play when the item goes on its disabled cooldown due to an attack.
|
||||
* Gets the sound to play when the item goes on its disabled cooldown due to an attack.
|
||||
*
|
||||
* @return a key of the sound
|
||||
* @return the sound
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@Nullable Key disableSound();
|
||||
@Nullable Sound disableSound();
|
||||
|
||||
/**
|
||||
* Builder for {@link BlocksAttacks}.
|
||||
@@ -107,10 +108,26 @@ public interface BlocksAttacks {
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder bypassedBy(@Nullable RegistryKeySet<DamageType> bypassedBy);
|
||||
|
||||
/**
|
||||
* Sets the sound to play when an attack is successfully blocked.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder blockSound(@Nullable Key sound);
|
||||
Builder blockSound(@Nullable Sound sound);
|
||||
|
||||
/**
|
||||
* Sets the sound to play when the item goes on its disabled cooldown due to an attack.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder disableSound(@Nullable Key sound);
|
||||
Builder disableSound(@Nullable Sound sound);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
|
||||
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -30,7 +31,7 @@ public interface Consumable extends BuildableDataComponent<Consumable, Consumabl
|
||||
ItemUseAnimation animation();
|
||||
|
||||
@Contract(pure = true)
|
||||
Key sound();
|
||||
Sound sound();
|
||||
|
||||
@Contract(pure = true)
|
||||
boolean hasConsumeParticles();
|
||||
@@ -65,11 +66,11 @@ public interface Consumable extends BuildableDataComponent<Consumable, Consumabl
|
||||
/**
|
||||
* Sets the sound played when consuming the item.
|
||||
*
|
||||
* @param sound the {@link Key} representing the sound to be used
|
||||
* @param sound the sound to be used
|
||||
* @return the builder for chaining
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder sound(Key sound);
|
||||
Builder sound(Sound sound);
|
||||
|
||||
/**
|
||||
* Sets whether consuming the item results in particle effects.
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.papermc.paper.datacomponent.BuildableDataComponent;
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -37,12 +38,12 @@ public interface Equippable extends BuildableDataComponent<Equippable, Equippabl
|
||||
EquipmentSlot slot();
|
||||
|
||||
/**
|
||||
* Gets the equip sound key.
|
||||
* Gets the equip sound.
|
||||
*
|
||||
* @return the equip sound key
|
||||
* @return the equip sound
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
Key equipSound();
|
||||
Sound equipSound();
|
||||
|
||||
/**
|
||||
* Gets the asset id if present.
|
||||
@@ -115,7 +116,7 @@ public interface Equippable extends BuildableDataComponent<Equippable, Equippabl
|
||||
* @return shear sound
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
Key shearSound();
|
||||
Sound shearSound();
|
||||
|
||||
/**
|
||||
* Builder for {@link Equippable}.
|
||||
@@ -124,13 +125,13 @@ public interface Equippable extends BuildableDataComponent<Equippable, Equippabl
|
||||
interface Builder extends DataComponentBuilder<Equippable> {
|
||||
|
||||
/**
|
||||
* Sets the equip sound key for this item.
|
||||
* Sets the equip sound for this item.
|
||||
*
|
||||
* @param sound the equip sound key
|
||||
* @param sound the equip sound
|
||||
* @return the builder for chaining
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder equipSound(Key sound);
|
||||
Builder equipSound(Sound sound);
|
||||
|
||||
/**
|
||||
* Sets the asset id for this item.
|
||||
@@ -207,10 +208,10 @@ public interface Equippable extends BuildableDataComponent<Equippable, Equippabl
|
||||
/**
|
||||
* Sets the sound that is played when shearing this equipment off an entity.
|
||||
*
|
||||
* @param shearSound the shear sound key
|
||||
* @param shearSound the shear sound
|
||||
* @return the builder for chaining
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder shearSound(Key shearSound);
|
||||
Builder shearSound(Sound shearSound);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -48,10 +49,10 @@ public interface KineticWeapon {
|
||||
float damageMultiplier();
|
||||
|
||||
@Contract(pure = true)
|
||||
@Nullable Key sound();
|
||||
@Nullable Sound sound();
|
||||
|
||||
@Contract(pure = true)
|
||||
@Nullable Key hitSound();
|
||||
@Nullable Sound hitSound();
|
||||
|
||||
interface Condition {
|
||||
|
||||
@@ -92,10 +93,26 @@ public interface KineticWeapon {
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder damageMultiplier(float damageMultiplier);
|
||||
|
||||
/**
|
||||
* Sets the sound to play while this weapon is active.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder sound(@Nullable Key sound);
|
||||
Builder sound(@Nullable Sound sound);
|
||||
|
||||
/**
|
||||
* Sets the sound to play when this weapon hits an entity.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder hitSound(@Nullable Key sound);
|
||||
Builder hitSound(@Nullable Sound sound);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
@@ -22,9 +23,9 @@ public interface PiercingWeapon {
|
||||
|
||||
boolean dismounts();
|
||||
|
||||
@Nullable Key sound();
|
||||
@Nullable Sound sound();
|
||||
|
||||
@Nullable Key hitSound();
|
||||
@Nullable Sound hitSound();
|
||||
|
||||
/**
|
||||
* Builder for {@link PiercingWeapon}.
|
||||
@@ -38,10 +39,26 @@ public interface PiercingWeapon {
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder dismounts(boolean dismounts);
|
||||
|
||||
/**
|
||||
* Sets the sound to play while this weapon is active.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder sound(@Nullable Key sound);
|
||||
Builder sound(@Nullable Sound sound);
|
||||
|
||||
/**
|
||||
* Sets the sound to play when this weapon hits an entity.
|
||||
*
|
||||
* @param sound the sound, or null to play no sound
|
||||
* @return the builder for chaining
|
||||
* @see Sound#create(net.kyori.adventure.key.Key, Float)
|
||||
* @see Sound#create(java.util.function.Consumer)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder hitSound(@Nullable Key sound);
|
||||
Builder hitSound(@Nullable Sound sound);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import java.util.Set;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -37,5 +38,8 @@ public interface TooltipDisplay {
|
||||
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder hiddenComponents(Set<DataComponentType> components);
|
||||
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder hiddenComponents(RegistryKeySet<DataComponentType> components);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
@@ -22,7 +23,7 @@ interface ConsumableTypesBridge {
|
||||
|
||||
ConsumeEffect.ClearAllStatusEffects clearAllStatusEffects();
|
||||
|
||||
ConsumeEffect.PlaySound playSoundEffect(Key sound);
|
||||
ConsumeEffect.PlaySound playSoundEffect(Sound sound);
|
||||
|
||||
ConsumeEffect.TeleportRandomly teleportRandomlyEffect(float diameter, boolean directionalParticles);
|
||||
}
|
||||
+5
-4
@@ -3,6 +3,7 @@ package io.papermc.paper.datacomponent.item.consumable;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -52,12 +53,12 @@ public interface ConsumeEffect {
|
||||
/**
|
||||
* Creates a consume effect that plays a sound on consumption.
|
||||
*
|
||||
* @param key the key sound effect to play
|
||||
* @param sound the sound effect to play
|
||||
* @return the effect instance
|
||||
*/
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
static PlaySound playSoundConsumeEffect(final Key key) {
|
||||
return ConsumableTypesBridge.bridge().playSoundEffect(key);
|
||||
static PlaySound playSoundConsumeEffect(final Sound sound) {
|
||||
return ConsumableTypesBridge.bridge().playSoundEffect(sound);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +129,7 @@ public interface ConsumeEffect {
|
||||
*
|
||||
* @return sound effect
|
||||
*/
|
||||
Key sound();
|
||||
Sound sound();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,9 @@ package io.papermc.paper.dialog;
|
||||
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.InlinedRegistryBuilderProvider;
|
||||
import io.papermc.paper.registry.data.RegistryBuilderProvider;
|
||||
import io.papermc.paper.registry.data.dialog.DialogRegistryEntry;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.dialog.DialogLike;
|
||||
@@ -19,7 +20,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
* Can also be created during bootstrap via {@link io.papermc.paper.registry.event.RegistryEvents#DIALOG}.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface Dialog extends Keyed, DialogLike {
|
||||
public interface Dialog extends RegistryElement.Inlineable<Dialog, DialogRegistryEntry, DialogRegistryEntry.Builder>, Keyed, DialogLike {
|
||||
|
||||
/**
|
||||
* Creates a new dialog using the provided builder.
|
||||
@@ -28,7 +29,7 @@ public interface Dialog extends Keyed, DialogLike {
|
||||
* @return a new dialog instance
|
||||
*/
|
||||
static Dialog create(final Consumer<RegistryBuilderFactory<Dialog, ? extends DialogRegistryEntry.Builder>> value) {
|
||||
return InlinedRegistryBuilderProvider.instance().createDialog(value);
|
||||
return RegistryBuilderProvider.instance().create(RegistryKey.DIALOG, value);
|
||||
}
|
||||
|
||||
// Start generate - Dialog
|
||||
|
||||
@@ -52,4 +52,13 @@ public interface PlayerPostEffects {
|
||||
*/
|
||||
boolean clear();
|
||||
|
||||
/**
|
||||
* Forces an immediate update of post-effects currently applied to the player.
|
||||
* <p>
|
||||
* Calling this method manually is usually unnecessary, as post-effects are automatically
|
||||
* synchronized at the end of the player entity tick. It should only be called if changes
|
||||
* need to be synchronized immediately.
|
||||
*/
|
||||
void update();
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.papermc.paper.entity.poi;
|
||||
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -15,7 +16,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
* @see PoiTypes
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PoiType extends Keyed {
|
||||
public interface PoiType extends RegistryElement<PoiType>, Keyed {
|
||||
|
||||
/**
|
||||
* Determines whether the provided BlockState is relevant to this
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package io.papermc.paper.event.entity;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.entity.EntityEvent;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when an {@link Entity} lands on the block after falling.
|
||||
* This event is called before {@link org.bukkit.event.entity.EntityDamageEvent}, {@link org.bukkit.event.entity.EntityChangeBlockEvent}, {@link org.bukkit.event.player.PlayerInteractEvent}
|
||||
* and {@link org.bukkit.event.entity.EntityInteractEvent}.
|
||||
*/
|
||||
@NullMarked
|
||||
public class EntityLandEvent extends EntityEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final Block block;
|
||||
private boolean cancelled;
|
||||
private double fallDistance;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public EntityLandEvent(final Entity entity, final Block block, final double fallDistance) {
|
||||
super(entity);
|
||||
this.block = block;
|
||||
this.fallDistance = fallDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the block that the entity landed on}
|
||||
*/
|
||||
public Block getBlock() {
|
||||
return this.block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to cancel the landing, cancelling this event will prevent
|
||||
* the entity from taking fall damage and interact with the block. (ex: break turtle egg)
|
||||
*
|
||||
* @param cancel true if the event should be cancelled, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public void setCancelled(final boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fall distance of the entity before landing.
|
||||
*
|
||||
* @return the fall distance
|
||||
*/
|
||||
public double getFallDistance() {
|
||||
return this.fallDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fall distance of the entity before landing.
|
||||
* Fall distance in the event is used to calculate fall damage and
|
||||
* the chance of transforming {@link org.bukkit.Material#FARMLAND} to {@link org.bukkit.Material#DIRT} and
|
||||
* the type of falling sound when the entity lands on {@link org.bukkit.Material#POWDER_SNOW}.
|
||||
*
|
||||
* @param fallDistance the fall distance
|
||||
* @throws IllegalArgumentException if the fall distance is negative or not finite
|
||||
*/
|
||||
public void setFallDistance(final @NonNegative double fallDistance) {
|
||||
Preconditions.checkArgument(
|
||||
Double.isFinite(fallDistance) && fallDistance >= 0.0,
|
||||
"Fall distance must be finite and non-negative"
|
||||
);
|
||||
this.fallDistance = fallDistance;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package io.papermc.paper.event.entity;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.entity.EntityEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when an entity is launched upward by a Potent Sulfur geyser.
|
||||
*/
|
||||
@NullMarked
|
||||
public class EntityPotentSulfurLaunchEvent extends EntityEvent {
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final Block sulfurBlock;
|
||||
private final Location sourceLocation;
|
||||
|
||||
private final Vector launchVelocity;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public EntityPotentSulfurLaunchEvent(
|
||||
final Entity entity,
|
||||
final Block sulfurBlock,
|
||||
final Location sourceLocation,
|
||||
final Vector launchVelocity
|
||||
) {
|
||||
super(entity);
|
||||
this.sulfurBlock = sulfurBlock;
|
||||
this.sourceLocation = sourceLocation;
|
||||
this.launchVelocity = launchVelocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Potent Sulfur block.
|
||||
*/
|
||||
public Block getSulfurBlock() {
|
||||
return this.sulfurBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location where the geyser exits the water column.
|
||||
*/
|
||||
public Location getSourceLocation() {
|
||||
return this.sourceLocation.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the velocity that will be added to the entity.
|
||||
* <br>
|
||||
* This value is read-only, changes made to it <b>will not</b> have any
|
||||
* effect on the final launch velocity.
|
||||
*/
|
||||
public Vector getLaunchVelocity() {
|
||||
return this.launchVelocity.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package io.papermc.paper.event.entity;
|
||||
|
||||
import org.bukkit.block.Container;
|
||||
import org.bukkit.entity.CopperGolem;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.entity.EntityEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when an item-transporting entity (ex a {@link CopperGolem})
|
||||
* is inspecting a destination {@link Container} to decide if the item it is holding
|
||||
* belongs in said container.
|
||||
* <br>
|
||||
* This gives plugin developers an opportunity to
|
||||
* override the {@link CopperGolem}'s sorting behavior.
|
||||
* <br>
|
||||
* <b>Note:</b> This event can be called twice during a single
|
||||
* "interaction", once before the container is opened, and again before items are
|
||||
* added and the container is closed.
|
||||
*/
|
||||
@NullMarked
|
||||
public class ItemTransportingEntitySortEvent extends EntityEvent {
|
||||
protected static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final ItemStack itemStack;
|
||||
private final Inventory containerInventory;
|
||||
private Result result;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ItemTransportingEntitySortEvent(
|
||||
final Entity entity,
|
||||
final ItemStack itemStack,
|
||||
final Inventory containerInventory
|
||||
) {
|
||||
super(entity);
|
||||
this.containerInventory = containerInventory;
|
||||
this.itemStack = itemStack;
|
||||
this.result = Result.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sorting decision for the held item and the inspected container.
|
||||
* <ul>
|
||||
* <li>{@link Result#ALLOW}: the item belongs in the container.</li>
|
||||
* <li>{@link Result#DENY}: the item does not belong in the container.</li>
|
||||
* <li>{@link Result#DEFAULT}: use the vanilla sorting logic.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param result the sorting decision
|
||||
* @see Result
|
||||
*/
|
||||
public void setResult(final Result result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current sorting decision. Starts as {@link Result#DEFAULT}
|
||||
* and may have been modified by other plugins.
|
||||
*
|
||||
* @return the current sorting decision
|
||||
* @see #setResult(Result)
|
||||
*/
|
||||
public Result getResult() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inventory of the container the entity is comparing
|
||||
* against the held item.
|
||||
*
|
||||
* @return the inventory of the potential destination container
|
||||
*/
|
||||
public Inventory getContainerInventory() {
|
||||
return this.containerInventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone of the ItemStack held by the entity that is being compared
|
||||
* against the container.
|
||||
*
|
||||
* @return The held ItemStack
|
||||
*/
|
||||
public ItemStack getItemStack() {
|
||||
return this.itemStack.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
package io.papermc.paper.event.inventory;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
/**
|
||||
* Called when a {@link Player} selects an item inside a bundle.
|
||||
*
|
||||
* @apiNote This event does not fire for bundle item selections in creative mode player inventories.
|
||||
*/
|
||||
@NullMarked
|
||||
public final class PlayerBundleItemSelectEvent extends InventoryEvent {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final ItemStack bundle;
|
||||
private final int rawSlot;
|
||||
private final int slot;
|
||||
|
||||
private final ItemStack previousItem;
|
||||
private final ItemStack selectedItem;
|
||||
|
||||
private final int previousIndex;
|
||||
private final int selectedIndex;
|
||||
private final Direction direction;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public PlayerBundleItemSelectEvent(final InventoryView view, final ItemStack bundle, final int rawSlot, final ItemStack previousItem, final ItemStack selectedItem, final int previousIndex, final int selectedIndex, final Direction direction) {
|
||||
super(view);
|
||||
|
||||
this.bundle = bundle;
|
||||
this.rawSlot = rawSlot;
|
||||
this.slot = view.convertSlot(rawSlot);
|
||||
|
||||
this.previousItem = previousItem;
|
||||
this.selectedItem = selectedItem;
|
||||
|
||||
this.previousIndex = previousIndex;
|
||||
this.selectedIndex = selectedIndex;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player who triggered the event.
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return (Player) this.getView().getPlayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bundle item.
|
||||
*
|
||||
* @return the bundle item
|
||||
*/
|
||||
public ItemStack getBundle() {
|
||||
return this.bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slot number of the bundle, depending on which {@link Inventory} it is located in.
|
||||
*
|
||||
* @return the slot number
|
||||
* @see InventoryClickEvent#getSlot()
|
||||
*/
|
||||
public int getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw slot number of the bundle inside the {@link InventoryView}.
|
||||
*
|
||||
* @return the raw slot number
|
||||
* @see InventoryClickEvent#getRawSlot()
|
||||
*/
|
||||
public int getRawSlot() {
|
||||
return this.rawSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previously selected item inside the bundle. If no item was previously selected, this will return an empty item.
|
||||
*
|
||||
* @return the previously selected item
|
||||
*/
|
||||
public ItemStack getPreviousItem() {
|
||||
return this.previousItem.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected item inside the bundle.
|
||||
*
|
||||
* @return the selected item
|
||||
*/
|
||||
public ItemStack getSelectedItem() {
|
||||
return this.selectedItem.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previously selected index. If no item was previously selected, this will be -1.
|
||||
*
|
||||
* @return the previously selected index
|
||||
*/
|
||||
public int getPreviousIndex() {
|
||||
return this.previousIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected index.
|
||||
*
|
||||
* @return the selected index
|
||||
*/
|
||||
public int getSelectedIndex() {
|
||||
return this.selectedIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the direction from the previous selection to the new one.
|
||||
*
|
||||
* @apiNote The direction cannot be reliably determined if there are less than three item stacks inside the bundle, in which case this returns {@link Direction#UNKNOWN}.
|
||||
*
|
||||
* @return the direction
|
||||
*/
|
||||
public Direction getDirection() {
|
||||
return this.direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a selection direction.
|
||||
*/
|
||||
public enum Direction {
|
||||
/**
|
||||
* Represents forward direction.
|
||||
*/
|
||||
FORWARD(OptionalInt.of(1)),
|
||||
/**
|
||||
* Represents backward direction.
|
||||
*/
|
||||
BACKWARD(OptionalInt.of(-1)),
|
||||
/**
|
||||
* Represents indeterminable direction.
|
||||
* <p>
|
||||
* That is, for bundles with less than three item stacks inside.
|
||||
*/
|
||||
UNKNOWN(OptionalInt.empty());
|
||||
|
||||
private final OptionalInt delta;
|
||||
|
||||
Direction(final OptionalInt delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the delta integer of the direction.
|
||||
* <p>
|
||||
* Directions are mapped the following:
|
||||
* <ul>
|
||||
* <li>{@link #FORWARD} to {@code +1}</li>
|
||||
* <li>{@link #BACKWARD} to {@code -1}</li>
|
||||
* <li>{@link #UNKNOWN} to {@link OptionalInt#empty()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the delta
|
||||
*/
|
||||
public OptionalInt getDelta() {
|
||||
return this.delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direction opposite to this direction.
|
||||
*
|
||||
* @return the flipped direction or {@link #UNKNOWN} if the direction is unknown
|
||||
*/
|
||||
public Direction flip() {
|
||||
return switch (this) {
|
||||
case FORWARD -> BACKWARD;
|
||||
case BACKWARD -> FORWARD;
|
||||
case UNKNOWN -> UNKNOWN;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package io.papermc.paper.event.inventory;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Called when a hopper or hopper minecart is about to choose an item to move,
|
||||
* before any {@link InventoryMoveItemEvent}.
|
||||
* <p>
|
||||
* The hopper treats disallowed slots of the source as if they do not exist, so
|
||||
* a source with items only in disallowed slots is treated as empty.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PrepareHopperTransferEvent extends Event {
|
||||
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final Inventory source;
|
||||
private final Inventory destination;
|
||||
private final boolean didSourceInitiate;
|
||||
protected long disallowedSlots;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public PrepareHopperTransferEvent(final Inventory source, final Inventory destination, final boolean didSourceInitiate) {
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.didSourceInitiate = didSourceInitiate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Inventory that items are being taken from
|
||||
*
|
||||
* @return Inventory that items are being taken from
|
||||
*/
|
||||
public Inventory getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Inventory that items are being put into
|
||||
*
|
||||
* @return Inventory that items are being put into
|
||||
*/
|
||||
public Inventory getDestination() {
|
||||
return this.destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Inventory that initiated the transfer. This will always be
|
||||
* either the destination or source Inventory.
|
||||
*
|
||||
* @return Inventory that initiated the transfer
|
||||
*/
|
||||
public Inventory getInitiator() {
|
||||
return this.didSourceInitiate ? this.source : this.destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the hopper is allowed to take items from a slot of {@link #getSource()}.
|
||||
*
|
||||
* @param slot the slot
|
||||
* @return true if the slot is allowed
|
||||
*/
|
||||
public boolean isSlotAllowed(final int slot) {
|
||||
Preconditions.checkArgument(slot >= 0 && slot < this.source.getSize(), "Slot %s is outside the source inventory", slot);
|
||||
return (this.disallowedSlots & (1L << slot)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the hopper is allowed to take items from a slot of {@link #getSource()}.
|
||||
*
|
||||
* @param slot the slot
|
||||
* @param allowed whether the slot is allowed
|
||||
*/
|
||||
public void setSlotAllowed(final int slot, final boolean allowed) {
|
||||
Preconditions.checkArgument(slot >= 0 && slot < this.source.getSize(), "Slot %s is outside the source inventory", slot);
|
||||
if (allowed) {
|
||||
this.disallowedSlots &= ~(1L << slot);
|
||||
} else {
|
||||
this.disallowedSlots |= 1L << slot;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import org.jspecify.annotations.NullMarked;
|
||||
* <p>
|
||||
* Adding or removing entities from the world at the point in time this event is called is completely
|
||||
* unsupported and should be avoided.
|
||||
* Teleporting entities in the world at the point in time this event is called yields an undefined tracker
|
||||
* behavior and should be avoided.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerTrackEntityEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.jspecify.annotations.NullMarked;
|
||||
* <p>
|
||||
* Adding or removing entities from the world at the point in time this event is called is completely
|
||||
* unsupported and should be avoided.
|
||||
* Teleporting entities in the world at the point in time this event is called yields an undefined tracker
|
||||
* behavior and should be avoided.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerUntrackEntityEvent extends PlayerEvent {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.papermc.paper.persistence;
|
||||
|
||||
import java.util.Set;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
@@ -66,6 +68,32 @@ public interface PersistentDataContainerView {
|
||||
*/
|
||||
boolean has(NamespacedKey key);
|
||||
|
||||
/**
|
||||
* Returns if the persistent metadata provider has metadata registered
|
||||
* matching the provided parameters.
|
||||
* <p>
|
||||
* This method will only return true if the found value has the same primitive
|
||||
* data type as the provided data key.
|
||||
* <p>
|
||||
* Storing a value using a custom {@link PersistentDataType} implementation
|
||||
* will not store the complex data type. Therefore, storing a UUID (by
|
||||
* storing a byte[]) will match has("key", {@link PersistentDataType#BYTE_ARRAY}).
|
||||
* Likewise, a stored byte[] will always match your UUID {@link PersistentDataType}
|
||||
* even if it is not 16 bytes long.
|
||||
* <p>
|
||||
* This method is only usable for custom object keys. Overwriting existing
|
||||
* tags, like the display name, will not work as the values are stored
|
||||
* using your namespace.
|
||||
*
|
||||
* @param dataKey the data key the value is stored under
|
||||
* @return if a value with the provided key and type exists
|
||||
* @throws IllegalArgumentException if the key to look up is null
|
||||
*/
|
||||
default boolean has(final PersistentDataKey<?> dataKey) {
|
||||
Preconditions.checkArgument(dataKey != null, "The data key cannot be null");
|
||||
return this.has(dataKey.key(), dataKey.dataType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata value that is stored on the
|
||||
* {@link PersistentDataHolder} instance.
|
||||
@@ -110,6 +138,63 @@ public interface PersistentDataContainerView {
|
||||
*/
|
||||
<P, C> C getOrDefault(NamespacedKey key, PersistentDataType<P, C> type, C defaultValue);
|
||||
|
||||
/**
|
||||
* Returns the metadata value that is stored on the
|
||||
* {@link PersistentDataHolder} instance.
|
||||
*
|
||||
* @param dataKey the data key to look up in the custom tag map
|
||||
* @param <C> the generic type of the eventually created complex object
|
||||
* @return the value or {@code null} if no value was mapped under the given
|
||||
* value
|
||||
* @throws IllegalArgumentException if the data key to look up is null
|
||||
* @throws IllegalArgumentException if a value exists under the given key,
|
||||
* but cannot be accessed using the given type
|
||||
* @throws IllegalArgumentException if no suitable adapter was found for
|
||||
* the {@link PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
default <C> @Nullable C get(final PersistentDataKey<C> dataKey) {
|
||||
Preconditions.checkArgument(dataKey != null, "The data key cannot be null");
|
||||
return this.get(dataKey.key(), dataKey.dataType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata value that is stored on the
|
||||
* {@link PersistentDataHolder} instance. If the value does not exist in the
|
||||
* container, the default value provided is returned.
|
||||
*
|
||||
* @param dataKey the data key to look up in the custom tag map
|
||||
* @param defaultValue the default value to return if no value was found for
|
||||
* the provided key
|
||||
* @param <C> the generic type of the eventually created complex object
|
||||
* @return the value or the default value if no value was mapped under the given key
|
||||
* @throws IllegalArgumentException if the data key to look up is null
|
||||
* @throws IllegalArgumentException if a value exists under the given key,
|
||||
* but cannot be accessed using the given type
|
||||
* @throws IllegalArgumentException if no suitable adapter was found for
|
||||
* the {@link PersistentDataType#getPrimitiveType()}
|
||||
*/
|
||||
default <C> C getOrDefault(final PersistentDataKey<C> dataKey, final C defaultValue) {
|
||||
Preconditions.checkArgument(dataKey != null, "The data key cannot be null");
|
||||
return this.getOrDefault(dataKey.key(), dataKey.dataType(), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates the {@link PersistentDataType} of the value based on the primitive
|
||||
* type that is stored for the given key.
|
||||
* <br>
|
||||
* <b>WARNING:</b> This method will only return data types
|
||||
* defined in {@link PersistentDataType} which directly map to a specific
|
||||
* nbt tag. The return value will be wrong if the data type is plugin
|
||||
* specific or not represented by a specific nbt tag.
|
||||
* Use {@link #has(NamespacedKey, PersistentDataType)} if you expect a
|
||||
* specific data type.
|
||||
*
|
||||
* @param key the key to look up the value type of
|
||||
* @return estimated data type or null if no value is present, the type is
|
||||
* unknown or an empty list is encountered as value.
|
||||
*/
|
||||
@Nullable PersistentDataType<?, ?> getPrimitiveStorageType(Key key);
|
||||
|
||||
/**
|
||||
* Get the set of keys present on this {@link PersistentDataContainer}
|
||||
* instance.
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.papermc.paper.persistence;
|
||||
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* This class represents the union of a {@link Key} and a
|
||||
* {@link PersistentDataType}.
|
||||
* <p>
|
||||
* The advantage of this class is more direct, typed access to data stored in a {@link PersistentDataContainer}.
|
||||
* Instead of having to keep track of the {@link NamespacedKey} and {@link PersistentDataType} separately
|
||||
* when working with PDC, this class allows you to store both together.
|
||||
* <p>
|
||||
* <h2>Example usage</h2>
|
||||
* <pre>{@code
|
||||
* public class CustomLogic {
|
||||
* public static final PersistentDataKey<Integer> TRACKED_VALUE = PersistentDataKey.of(
|
||||
* Key.key("custom:tracked_value"),
|
||||
* PersistentDataType.INTEGER
|
||||
* );
|
||||
* public static final PersistentDataKey<UUID> OWNING_PLAYER = PersistentDataKey.of(
|
||||
* Key.key("custom:owning_player"),
|
||||
* new UUIDTagType() // Custom type
|
||||
* );
|
||||
*
|
||||
* // Checks if the stored PDC value for OWNING_PLAYER matches the executor UUID and adds
|
||||
* // 1 to the TRACKED_VALUE, if it does.
|
||||
* public static void incrementIfOwner(PersistentDataContainer pdc, UUID executor) {
|
||||
* if (!Objects.equals(pdc.get(OWNING_PLAYER), executor) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* pdc.set(TRACKED_VALUE, pdc.getOrDefault(TRACKED_VALUE, 0) + 1);
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param <C> the retrieved object type when applying this tag type
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PersistentDataKey<C> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link PersistentDataKey} with the given {@link Key} and {@link PersistentDataType}.
|
||||
*
|
||||
* @param key the access key to store
|
||||
* @param type the persistent data type to reference
|
||||
* @param <C> the retrieved object type when applying this tag type
|
||||
* @return a new {@link PersistentDataKey} of the given key and type
|
||||
* @throws IllegalArgumentException if either key or type are null
|
||||
*/
|
||||
static <C> PersistentDataKey<C> of(final Key key, final PersistentDataType<?, C> type) {
|
||||
return InternalAPIBridge.get().createPersistentDataKey(key, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the access key of this {@link PersistentDataKey}}
|
||||
*/
|
||||
NamespacedKey key();
|
||||
|
||||
/**
|
||||
* {@return the data type of this {@link PersistentDataKey}}
|
||||
*/
|
||||
PersistentDataType<?, C> dataType();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.papermc.paper.registry;
|
||||
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* An element tied to a registry.
|
||||
* <p>
|
||||
* For unregistered element, the equality methods exposed here will always return {@code false}
|
||||
* as there's no way to identify them with a key.
|
||||
*
|
||||
* @see RegistryKey
|
||||
* @see org.bukkit.Registry
|
||||
* @see org.bukkit.Registry#getKey(org.bukkit.Keyed)
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Experimental
|
||||
public interface RegistryElement<T> {
|
||||
|
||||
/**
|
||||
* Checks whether this element is identified by the given key.
|
||||
*
|
||||
* @param type the key
|
||||
* @return whether this element is identified by the given key.
|
||||
*/
|
||||
boolean is(TypedKey<T> type);
|
||||
|
||||
/**
|
||||
* Checks whether this element is identified by the given key.
|
||||
*
|
||||
* @param type the key
|
||||
* @return whether this element is identified by the given key
|
||||
*/
|
||||
boolean is(Key type);
|
||||
|
||||
/**
|
||||
* Checks whether this element is contained in the
|
||||
* tag identified by the given tag key.
|
||||
*
|
||||
* @param type the tag key
|
||||
* @return whether this element is contained in the tag
|
||||
*/
|
||||
boolean is(TagKey<T> type);
|
||||
|
||||
/**
|
||||
* Marker interface for registered types that link an API type to its
|
||||
* registry entry and builder types.
|
||||
*
|
||||
* @param <T> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@ApiStatus.Experimental
|
||||
interface Buildable<T, E, B extends RegistryBuilder<T>> extends RegistryElement<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Marker interface for registered types that are valid to be constructed inline.
|
||||
*
|
||||
* @param <T> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface Inlineable<T, E, B extends RegistryBuilder<T>> extends RegistryElement.Buildable<T, E, B> {
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package io.papermc.paper.registry;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
@@ -12,14 +10,13 @@ import org.jspecify.annotations.NullMarked;
|
||||
* @param <T> the value type for the registry
|
||||
*/
|
||||
@NullMarked
|
||||
public sealed interface TypedKey<T> extends Key permits TypedKeyImpl {
|
||||
public sealed interface TypedKey<T> permits TypedKeyImpl {
|
||||
|
||||
/**
|
||||
* Gets the key for the value in the registry.
|
||||
*
|
||||
* @return the value's key
|
||||
*/
|
||||
@Override
|
||||
Key key();
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
package io.papermc.paper.registry;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
record TypedKeyImpl<T>(Key key, RegistryKey<T> registryKey) implements TypedKey<T> {
|
||||
// Wrap key methods to make this easier to use
|
||||
@KeyPattern.Namespace
|
||||
@Override
|
||||
public String namespace() {
|
||||
return this.key.namespace();
|
||||
}
|
||||
|
||||
@KeyPattern.Value
|
||||
@Override
|
||||
public String value() {
|
||||
return this.key.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return this.key.asString();
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,7 @@ public interface EnchantmentRegistryEntry {
|
||||
* @param supportedItems the registry key set representing the supported items
|
||||
* @return this builder instance
|
||||
* @see RegistrySet#keySet(RegistryKey, TypedKey[])
|
||||
* @see RegistrySet#keySet(TypedKey, TypedKey[])
|
||||
* @see RegistryComposeEvent#getOrCreateTag(TagKey)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
@@ -182,6 +183,7 @@ public interface EnchantmentRegistryEntry {
|
||||
* @param primaryItems the registry key set representing the primary items.
|
||||
* @return this builder instance.
|
||||
* @see RegistrySet#keySet(RegistryKey, TypedKey[])
|
||||
* @see RegistrySet#keySet(TypedKey, TypedKey[])
|
||||
* @see RegistryComposeEvent#getOrCreateTag(TagKey)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
@@ -285,6 +287,7 @@ public interface EnchantmentRegistryEntry {
|
||||
* @param exclusiveWith a registry set of enchantments exclusive to this one
|
||||
* @return this builder instance
|
||||
* @see RegistrySet#keySet(RegistryKey, TypedKey[])
|
||||
* @see RegistrySet#keySet(TypedKey, TypedKey[])
|
||||
* @see RegistryComposeEvent#getOrCreateTag(TagKey)
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package io.papermc.paper.registry.data;
|
||||
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.data.dialog.DialogRegistryEntry;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.MusicInstrument;
|
||||
import org.bukkit.inventory.meta.trim.TrimMaterial;
|
||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@ApiStatus.NonExtendable
|
||||
public interface InlinedRegistryBuilderProvider {
|
||||
|
||||
static InlinedRegistryBuilderProvider instance() {
|
||||
final class Holder {
|
||||
static final Optional<InlinedRegistryBuilderProvider> INSTANCE = ServiceLoader.load(InlinedRegistryBuilderProvider.class, InlinedRegistryBuilderProvider.class.getClassLoader()).findFirst();
|
||||
}
|
||||
return Holder.INSTANCE.orElseThrow();
|
||||
}
|
||||
|
||||
MusicInstrument createInstrument(Consumer<RegistryBuilderFactory<MusicInstrument, ? extends InstrumentRegistryEntry.Builder>> value);
|
||||
|
||||
Dialog createDialog(Consumer<RegistryBuilderFactory<Dialog, ? extends DialogRegistryEntry.Builder>> value);
|
||||
|
||||
TrimMaterial createTrimMaterial(Consumer<RegistryBuilderFactory<TrimMaterial, ? extends TrimMaterialRegistryEntry.Builder>> value);
|
||||
|
||||
TrimPattern createTrimPattern(Consumer<RegistryBuilderFactory<TrimPattern, ? extends TrimPatternRegistryEntry.Builder>> value);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.papermc.paper.registry.data;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.holder.RegistryHolder;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@ApiStatus.NonExtendable
|
||||
public interface RegistryBuilderProvider {
|
||||
|
||||
static RegistryBuilderProvider instance() {
|
||||
final class Holder {
|
||||
static final Optional<RegistryBuilderProvider> INSTANCE = ServiceLoader.load(RegistryBuilderProvider.class, RegistryBuilderProvider.class.getClassLoader()).findFirst();
|
||||
}
|
||||
return Holder.INSTANCE.orElseThrow();
|
||||
}
|
||||
|
||||
static <T extends RegistryElement.Buildable<T, E, ?>, E> RegistryHolder<T, E> transientHolder(final TypedKey<T> key) {
|
||||
return instance().createTransientReferenceHolder(key);
|
||||
}
|
||||
|
||||
<T extends RegistryElement.Inlineable<T, ?, B> & Keyed, B extends RegistryBuilder<T>> T create(RegistryKey<T> key, Consumer<RegistryBuilderFactory<T, ? extends B>> value);
|
||||
|
||||
<T extends RegistryElement.Buildable<T, E, ?>, E> RegistryHolder.Reference<T, E> createTransientReferenceHolder(TypedKey<T> key);
|
||||
}
|
||||
+23
-9
@@ -2,6 +2,7 @@ package io.papermc.paper.registry.data;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.holder.RegistryHolder;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import java.util.List;
|
||||
import org.bukkit.Sound;
|
||||
@@ -16,6 +17,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import static io.papermc.paper.registry.data.RegistryBuilderProvider.transientHolder;
|
||||
import static io.papermc.paper.util.BoundChecker.requireNonNegative;
|
||||
import static io.papermc.paper.util.BoundChecker.requirePositive;
|
||||
|
||||
@@ -180,18 +182,15 @@ public interface SulfurCubeArchetypeRegistryEntry {
|
||||
@ApiStatus.NonExtendable
|
||||
interface SoundSettings {
|
||||
|
||||
// todo The sounds should take a RegistryHolder but need more thoughts on the create method
|
||||
/**
|
||||
* {@return the sound played once the sulfur cube is knocked}
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
TypedKey<Sound> hitSound();
|
||||
RegistryHolder<Sound, SoundEventRegistryEntry> hitSound();
|
||||
|
||||
/**
|
||||
* {@return the sound played once the sulfur cube is pushed}
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
TypedKey<Sound> pushSound();
|
||||
RegistryHolder<Sound, SoundEventRegistryEntry> pushSound();
|
||||
|
||||
/**
|
||||
* {@return the smallest impulse required to play the push sound}
|
||||
@@ -199,7 +198,7 @@ public interface SulfurCubeArchetypeRegistryEntry {
|
||||
float pushSoundImpulseThreshold();
|
||||
|
||||
/**
|
||||
* {@return the amount of seconds before the push sound can be played again}
|
||||
* {@return the number of seconds before the push sound can be played again}
|
||||
*/
|
||||
float pushSoundCooldown();
|
||||
|
||||
@@ -209,13 +208,28 @@ public interface SulfurCubeArchetypeRegistryEntry {
|
||||
* @param hitSound the sound played once the sulfur cube is knocked, as returned by {@link #hitSound()}
|
||||
* @param pushSound the sound played once the sulfur cube is pushed, as returned by {@link #pushSound()}
|
||||
* @param pushSoundImpulseThreshold the smallest impulse required to play the push sound, as returned by {@link #pushSoundImpulseThreshold()}
|
||||
* @param pushSoundCooldown the amount of seconds before the push sound can be played again, as returned by {@link #pushSoundCooldown()}
|
||||
* @param pushSoundCooldown the number of seconds before the push sound can be played again, as returned by {@link #pushSoundCooldown()}
|
||||
* @return the created instance
|
||||
*/
|
||||
@Contract(value = "_, _, _, _ -> new", pure = true)
|
||||
@ApiStatus.Experimental
|
||||
static SoundSettings of(final TypedKey<Sound> hitSound, final TypedKey<Sound> pushSound, final float pushSoundImpulseThreshold, final float pushSoundCooldown) {
|
||||
record Impl(TypedKey<Sound> hitSound, TypedKey<Sound> pushSound, float pushSoundImpulseThreshold, float pushSoundCooldown) implements SoundSettings {
|
||||
return of(transientHolder(hitSound), transientHolder(pushSound), pushSoundImpulseThreshold, pushSoundCooldown);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new sound settings instance based on the passed values.
|
||||
* <p>
|
||||
* {@link RegistryHolder} instances can be created with {@link io.papermc.paper.registry.event.RegistryFactory}.
|
||||
*
|
||||
* @param hitSound the sound played once the sulfur cube is knocked, as returned by {@link #hitSound()}
|
||||
* @param pushSound the sound played once the sulfur cube is pushed, as returned by {@link #pushSound()}
|
||||
* @param pushSoundImpulseThreshold the smallest impulse required to play the push sound, as returned by {@link #pushSoundImpulseThreshold()}
|
||||
* @param pushSoundCooldown the number of seconds before the push sound can be played again, as returned by {@link #pushSoundCooldown()}
|
||||
* @return the created instance
|
||||
*/
|
||||
@Contract(value = "_, _, _, _ -> new", pure = true)
|
||||
static SoundSettings of(final RegistryHolder<Sound, SoundEventRegistryEntry> hitSound, final RegistryHolder<Sound, SoundEventRegistryEntry> pushSound, final float pushSoundImpulseThreshold, final float pushSoundCooldown) {
|
||||
record Impl(RegistryHolder<Sound, SoundEventRegistryEntry> hitSound, RegistryHolder<Sound, SoundEventRegistryEntry> pushSound, float pushSoundImpulseThreshold, float pushSoundCooldown) implements SoundSettings {
|
||||
}
|
||||
|
||||
return new Impl(hitSound, pushSound, pushSoundImpulseThreshold, pushSoundCooldown);
|
||||
|
||||
@@ -48,8 +48,10 @@ public interface DialogRegistryEntry {
|
||||
* <p>Not a part of the registry entry.</p>
|
||||
*
|
||||
* @return a new registry value set builder
|
||||
* @deprecated use {@link io.papermc.paper.registry.event.RegistryFactory} on the registry event and {@link io.papermc.paper.registry.set.RegistryHolderSetBuilder}
|
||||
*/
|
||||
@Contract(value = "-> new", pure = true)
|
||||
@Deprecated(since = "26.4", forRemoval = true)
|
||||
RegistryValueSetBuilder<Dialog, DialogRegistryEntry.Builder> registryValueSet();
|
||||
|
||||
/**
|
||||
|
||||
+5
-5
@@ -114,7 +114,7 @@ public non-sealed interface TextDialogInput extends DialogInput {
|
||||
* @return this builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder width(final @Range(from = 1, to = 1024) int width);
|
||||
Builder width(@Range(from = 1, to = 1024) int width);
|
||||
|
||||
/**
|
||||
* Sets whether the label should be visible.
|
||||
@@ -123,7 +123,7 @@ public non-sealed interface TextDialogInput extends DialogInput {
|
||||
* @return this builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder labelVisible(final boolean labelVisible);
|
||||
Builder labelVisible(boolean labelVisible);
|
||||
|
||||
/**
|
||||
* Sets the initial value of the input.
|
||||
@@ -132,7 +132,7 @@ public non-sealed interface TextDialogInput extends DialogInput {
|
||||
* @return this builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder initial(final String initial);
|
||||
Builder initial(String initial);
|
||||
|
||||
/**
|
||||
* Sets the maximum length of the input.
|
||||
@@ -141,7 +141,7 @@ public non-sealed interface TextDialogInput extends DialogInput {
|
||||
* @return this builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder maxLength(final @Positive int maxLength);
|
||||
Builder maxLength(@Positive int maxLength);
|
||||
|
||||
/**
|
||||
* Sets the multiline options for the input.
|
||||
@@ -150,7 +150,7 @@ public non-sealed interface TextDialogInput extends DialogInput {
|
||||
* @return this builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder multiline(final @Nullable MultilineOptions multiline);
|
||||
Builder multiline(@Nullable MultilineOptions multiline);
|
||||
|
||||
/**
|
||||
* Builds the text dialog input.
|
||||
|
||||
+3
-3
@@ -61,7 +61,7 @@ public non-sealed interface DialogListType extends DialogType {
|
||||
* @return the builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder exitAction(final @Nullable ActionButton exitAction);
|
||||
Builder exitAction(@Nullable ActionButton exitAction);
|
||||
|
||||
/**
|
||||
* Sets the number of columns to display in the dialog list.
|
||||
@@ -70,7 +70,7 @@ public non-sealed interface DialogListType extends DialogType {
|
||||
* @return the builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder columns(final @Positive int columns);
|
||||
Builder columns(@Positive int columns);
|
||||
|
||||
/**
|
||||
* Sets the width of each button in the dialog list.
|
||||
@@ -79,7 +79,7 @@ public non-sealed interface DialogListType extends DialogType {
|
||||
* @return the builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder buttonWidth(final @Range(from = 1, to = 1024) int buttonWidth);
|
||||
Builder buttonWidth(@Range(from = 1, to = 1024) int buttonWidth);
|
||||
|
||||
/**
|
||||
* Builds the dialog list type.
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ public non-sealed interface MultiActionType extends DialogType {
|
||||
* @return the builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder exitAction(final @Nullable ActionButton exitAction);
|
||||
Builder exitAction(@Nullable ActionButton exitAction);
|
||||
|
||||
/**
|
||||
* Sets the number of columns to display in the dialog.
|
||||
@@ -62,7 +62,7 @@ public non-sealed interface MultiActionType extends DialogType {
|
||||
* @return the builder
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder columns(final @Positive int columns);
|
||||
Builder columns(@Positive int columns);
|
||||
|
||||
/**
|
||||
* Builds the multi-action dialog.
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Event object for {@link RegistryEventProvider#compose()}. This
|
||||
* Event object for {@link RegistryEvents#compose(io.papermc.paper.registry.RegistryKey)}. This
|
||||
* event is fired after a registry is loaded with its normal values.
|
||||
* It provides a way for plugins to add new objects to the registry.
|
||||
*
|
||||
@@ -34,4 +34,11 @@ public interface RegistryComposeEvent<T, B extends RegistryBuilder<T>> extends R
|
||||
* @param <V> the tag value type
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey); // TODO remove Keyed
|
||||
|
||||
/**
|
||||
* Gets the factory for creating tags, holders, and holder sets.
|
||||
*
|
||||
* @return the registry factory
|
||||
*/
|
||||
RegistryFactory factory();
|
||||
}
|
||||
@@ -8,8 +8,8 @@ import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Event object for {@link RegistryEventProvider#entryAdd()}. This
|
||||
* event is fired right before a specific entry is registered in/added to registry.
|
||||
* Event object for {@link RegistryEvents#entryAdd(io.papermc.paper.registry.RegistryKey)}. This
|
||||
* event is fired right before a specific entry is registered in/added to the registry.
|
||||
* It provides a way for plugins to modify parts of this entry.
|
||||
*
|
||||
* @param <T> registry entry type
|
||||
@@ -42,4 +42,11 @@ public interface RegistryEntryAddEvent<T, B extends RegistryBuilder<T>> extends
|
||||
* @param <V> the tag value type
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey);
|
||||
|
||||
/**
|
||||
* Gets the factory for creating tags, holders, and holder sets.
|
||||
*
|
||||
* @return the registry factory
|
||||
*/
|
||||
RegistryFactory factory();
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.event.type.RegistryEntryAddEventType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -19,9 +20,11 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
*
|
||||
* @param <T> registry entry type
|
||||
* @param <B> registry entry builder type
|
||||
* @deprecated use {@link RegistryEvents#compose(RegistryKey)} and {@link RegistryEvents#entryAdd(RegistryKey)}
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface RegistryEventProvider<T, B extends RegistryBuilder<T>> {
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public interface RegistryEventProvider<T extends RegistryElement.Buildable<T, ?, B>, B extends RegistryBuilder<T>> {
|
||||
|
||||
/**
|
||||
* Gets the event type for {@link RegistryEntryAddEvent} which is fired just before
|
||||
|
||||
+5
-4
@@ -3,24 +3,25 @@ package io.papermc.paper.registry.event;
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.event.type.RegistryEntryAddEventType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Internal
|
||||
record RegistryEventProviderImpl<T, B extends RegistryBuilder<T>>(RegistryKey<T> registryKey) implements RegistryEventProvider<T, B> {
|
||||
record RegistryEventProviderImpl<T extends RegistryElement.Buildable<T, E, B>, E, B extends RegistryBuilder<T>>(RegistryKey<T> registryKey) implements RegistryEventProvider<T, B> {
|
||||
|
||||
static <T, B extends RegistryBuilder<T>> RegistryEventProvider<T, B> create(final RegistryKey<T> registryKey) {
|
||||
static <T extends RegistryElement.Buildable<T, E, B>, E, B extends RegistryBuilder<T>> RegistryEventProvider<T, B> create(final RegistryKey<T> registryKey) {
|
||||
return new RegistryEventProviderImpl<>(registryKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntryAddEventType<T, B> entryAdd() {
|
||||
return RegistryEventTypeProvider.provider().registryEntryAdd(this);
|
||||
return RegistryEvents.entryAdd(this.registryKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<T, B>> compose() {
|
||||
return RegistryEventTypeProvider.provider().registryCompose(this);
|
||||
return RegistryEvents.compose(this.registryKey);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -3,6 +3,8 @@ package io.papermc.paper.registry.event;
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.event.type.RegistryEntryAddEventType;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
@@ -17,7 +19,7 @@ interface RegistryEventTypeProvider {
|
||||
return PROVIDER.orElseThrow(() -> new IllegalStateException("Could not find a %s service implementation".formatted(RegistryEventTypeProvider.class.getSimpleName())));
|
||||
}
|
||||
|
||||
<T, B extends RegistryBuilder<T>> RegistryEntryAddEventType<T, B> registryEntryAdd(RegistryEventProvider<T, B> type);
|
||||
<API extends RegistryElement.Buildable<API, E, B>, E, B extends RegistryBuilder<API>> RegistryEntryAddEventType<API, B> registryEntryAdd(RegistryKey<API> key);
|
||||
|
||||
<T, B extends RegistryBuilder<T>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<T, B>> registryCompose(RegistryEventProvider<T, B> type);
|
||||
<API extends RegistryElement.Buildable<API, E, B>, E, B extends RegistryBuilder<API>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<API, B>> registryCompose(RegistryKey<API> key);
|
||||
}
|
||||
@@ -2,6 +2,10 @@ package io.papermc.paper.registry.event;
|
||||
|
||||
import io.papermc.paper.block.pot.PotPatternType;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEventType;
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
|
||||
import io.papermc.paper.registry.data.CatTypeRegistryEntry;
|
||||
@@ -22,6 +26,7 @@ import io.papermc.paper.registry.data.TrimPatternRegistryEntry;
|
||||
import io.papermc.paper.registry.data.WolfVariantRegistryEntry;
|
||||
import io.papermc.paper.registry.data.ZombieNautilusVariantRegistryEntry;
|
||||
import io.papermc.paper.registry.data.dialog.DialogRegistryEntry;
|
||||
import io.papermc.paper.registry.event.type.RegistryEntryAddEventType;
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.GameEvent;
|
||||
import org.bukkit.JukeboxSong;
|
||||
@@ -43,32 +48,141 @@ import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||
import static io.papermc.paper.registry.event.RegistryEventProviderImpl.create;
|
||||
|
||||
/**
|
||||
* Holds providers for {@link RegistryEntryAddEvent} and {@link RegistryComposeEvent}
|
||||
* handlers for each applicable registry.
|
||||
* Holds methods to create registry event types for various registry-related events.
|
||||
*/
|
||||
public final class RegistryEvents {
|
||||
|
||||
// Start generate - RegistryEvents
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<TrimMaterial, TrimMaterialRegistryEntry.Builder> TRIM_MATERIAL = create(RegistryKey.TRIM_MATERIAL);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<TrimPattern, TrimPatternRegistryEntry.Builder> TRIM_PATTERN = create(RegistryKey.TRIM_PATTERN);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<DamageType, DamageTypeRegistryEntry.Builder> DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Wolf.Variant, WolfVariantRegistryEntry.Builder> WOLF_VARIANT = create(RegistryKey.WOLF_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<JukeboxSong, JukeboxSongRegistryEntry.Builder> JUKEBOX_SONG = create(RegistryKey.JUKEBOX_SONG);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<PatternType, BannerPatternRegistryEntry.Builder> BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<PotPatternType, DecoratedPotPatternRegistryEntry.Builder> DECORATED_POT_PATTERN = create(RegistryKey.DECORATED_POT_PATTERN);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<MusicInstrument, InstrumentRegistryEntry.Builder> INSTRUMENT = create(RegistryKey.INSTRUMENT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Cat.Type, CatTypeRegistryEntry.Builder> CAT_VARIANT = create(RegistryKey.CAT_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Frog.Variant, FrogVariantRegistryEntry.Builder> FROG_VARIANT = create(RegistryKey.FROG_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Chicken.Variant, ChickenVariantRegistryEntry.Builder> CHICKEN_VARIANT = create(RegistryKey.CHICKEN_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Cow.Variant, CowVariantRegistryEntry.Builder> COW_VARIANT = create(RegistryKey.COW_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Pig.Variant, PigVariantRegistryEntry.Builder> PIG_VARIANT = create(RegistryKey.PIG_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<ZombieNautilus.Variant, ZombieNautilusVariantRegistryEntry.Builder> ZOMBIE_NAUTILUS_VARIANT = create(RegistryKey.ZOMBIE_NAUTILUS_VARIANT);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<SulfurCube.Archetype, SulfurCubeArchetypeRegistryEntry.Builder> SULFUR_CUBE_ARCHETYPE = create(RegistryKey.SULFUR_CUBE_ARCHETYPE);
|
||||
/**
|
||||
* @deprecated use {@link #entryAdd(RegistryKey)} and {@link #compose(RegistryKey)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "26.4")
|
||||
public static final RegistryEventProvider<Dialog, DialogRegistryEntry.Builder> DIALOG = create(RegistryKey.DIALOG);
|
||||
// End generate - RegistryEvents
|
||||
|
||||
/**
|
||||
* Gets the event type for {@link RegistryEntryAddEvent} which is fired just before
|
||||
* an object is added to a registry.
|
||||
* <p>
|
||||
* Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventType, io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler)}
|
||||
* to register a handler for {@link RegistryEntryAddEvent}.
|
||||
*
|
||||
* @param registryKey the registry key
|
||||
* @param <API> the api type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the registry entry builder type
|
||||
*
|
||||
* @return the registry entry add event type
|
||||
*/
|
||||
public static <API extends RegistryElement.Buildable<API, E, B>, E, B extends RegistryBuilder<API>> RegistryEntryAddEventType<API, B> entryAdd(final RegistryKey<API> registryKey) {
|
||||
return RegistryEventTypeProvider.provider().registryEntryAdd(registryKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event type for {@link RegistryComposeEvent} which is fired after
|
||||
* a registry is loaded of expected elements. It allows for the registration of new objects.
|
||||
* <p>
|
||||
* Can be used in {@link io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager#registerEventHandler(LifecycleEventType, io.papermc.paper.plugin.lifecycle.event.handler.LifecycleEventHandler)}
|
||||
* to register a handler for {@link RegistryComposeEvent}.
|
||||
*
|
||||
* @param registryKey the registry key
|
||||
* @param <API> the api type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the registry entry builder type
|
||||
*
|
||||
* @return the registry compose event type
|
||||
*/
|
||||
public static <API extends RegistryElement.Buildable<API, E, B>, E, B extends RegistryBuilder<API>> LifecycleEventType.Prioritizable<BootstrapContext, RegistryComposeEvent<API, B>> compose(final RegistryKey<API> registryKey) {
|
||||
return RegistryEventTypeProvider.provider().registryCompose(registryKey);
|
||||
}
|
||||
|
||||
private RegistryEvents() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package io.papermc.paper.registry.event;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.holder.RegistryHolder;
|
||||
import io.papermc.paper.registry.set.RegistryHolderSetBuilder;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import java.util.function.Consumer;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* A factory for creating tags, holders, and holder sets while
|
||||
* reacting to registry events.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public interface RegistryFactory {
|
||||
|
||||
/**
|
||||
* Gets or creates a tag for the given tag key. This tag
|
||||
* is then required to be filled either from the built-in or
|
||||
* custom datapack.
|
||||
*
|
||||
* @param tagKey the tag key
|
||||
* @return the tag
|
||||
* @param <V> the tag value type
|
||||
*/
|
||||
<V extends Keyed> Tag<V> getOrCreateTag(TagKey<V> tagKey); // TODO remove Keyed
|
||||
|
||||
/**
|
||||
* Gets or creates a reference holder for the given key. The referenced
|
||||
* value does not need to be present in the registry yet.
|
||||
* <p>
|
||||
* You can only create new reference holders for registries in the same registry layer. For example,
|
||||
* since {@link RegistryKey#SOUND_EVENT} is a built-in registry, you cannot create new
|
||||
* reference holders while in an event for {@link RegistryKey#SULFUR_CUBE_ARCHETYPE} as that
|
||||
* is in a later layer. Try a {@link #createInlinedHolder(RegistryKey, Consumer)}.
|
||||
*
|
||||
* @param key the key of the referenced value
|
||||
* @return the reference holder
|
||||
* @param <V> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
* @see #createInlinedHolder(RegistryKey, Consumer)
|
||||
*/
|
||||
<V extends Keyed & RegistryElement.Buildable<V, E, B>, E, B extends RegistryBuilder<V>> RegistryHolder.Reference<V, E> getOrCreateReferenceHolder(TypedKey<V> key); // TODO remove Keyed
|
||||
|
||||
/**
|
||||
* Creates an inlined holder wrapping an anonymous value built from the
|
||||
* given builder consumer.
|
||||
*
|
||||
* @param registryKey the registry key for the value's type
|
||||
* @param value a consumer configuring the inlined value's builder
|
||||
* @return the inlined holder
|
||||
* @param <V> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
* @see #getOrCreateReferenceHolder(TypedKey)
|
||||
*/
|
||||
<V extends Keyed & RegistryElement.Inlineable<V, E, B>, E, B extends RegistryBuilder<V>> RegistryHolder.Inlined<V, E> createInlinedHolder(RegistryKey<V> registryKey, Consumer<RegistryBuilderFactory<V, ? extends B>> value); // TODO remove Keyed
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link RegistryHolderSetBuilder holder set} of the given registry.
|
||||
*
|
||||
* @param registryKey the registry key for the value's type
|
||||
* @return a new holder set builder
|
||||
* @param <V> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
*/
|
||||
<V extends Keyed & RegistryElement.Inlineable<V, E, B>, E, B extends RegistryBuilder<V>> RegistryHolderSetBuilder<V, E, B> createSetBuilder(RegistryKey<V> registryKey); // TODO remove Keyed
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.papermc.paper.registry.holder;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@@ -12,7 +14,28 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
* @param <ENTRY> the type of the registry entry (for inlined values)
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public sealed interface RegistryHolder<API, ENTRY> permits RegistryHolder.Reference, RegistryHolder.Inlined {
|
||||
public sealed interface RegistryHolder<API extends RegistryElement.Buildable<API, ENTRY, ?>, ENTRY> permits RegistryHolder.Reference, RegistryHolder.Inlined {
|
||||
|
||||
/**
|
||||
* Gets the registry key of the registry this holder's value belongs to.
|
||||
*
|
||||
* @return the registry key
|
||||
*/
|
||||
RegistryKey<API> registryKey();
|
||||
|
||||
/**
|
||||
* Gets the value held by this holder.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
API value();
|
||||
|
||||
/**
|
||||
* Gets the registry entry held by this holder.
|
||||
*
|
||||
* @return the entry
|
||||
*/
|
||||
ENTRY entry();
|
||||
|
||||
/**
|
||||
* A holder that references a registry value by key, but does not have the entry itself.
|
||||
@@ -22,7 +45,7 @@ public sealed interface RegistryHolder<API, ENTRY> permits RegistryHolder.Refere
|
||||
* @param <ENTRY> the type of the registry entry
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
non-sealed interface Reference<API, ENTRY> extends RegistryHolder<API, ENTRY> {
|
||||
non-sealed interface Reference<API extends RegistryElement.Buildable<API, ENTRY, ?>, ENTRY> extends RegistryHolder<API, ENTRY> {
|
||||
|
||||
/**
|
||||
* The key of the referenced value.
|
||||
@@ -39,13 +62,14 @@ public sealed interface RegistryHolder<API, ENTRY> permits RegistryHolder.Refere
|
||||
* @param <ENTRY> the type of the registry entry
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
non-sealed interface Inlined<API, ENTRY> extends RegistryHolder<API, ENTRY> {
|
||||
non-sealed interface Inlined<API extends RegistryElement.Buildable<API, ENTRY, ?>, ENTRY> extends RegistryHolder<API, ENTRY> {
|
||||
|
||||
/**
|
||||
* The inlined entry.
|
||||
*
|
||||
* @return the inlined entry
|
||||
*/
|
||||
@Override
|
||||
ENTRY entry();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.papermc.paper.registry.set;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.holder.RegistryHolder;
|
||||
import java.util.Collection;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
/**
|
||||
* A {@link RegistrySet} backed by {@link RegistryHolder holders}, each of which is
|
||||
* either a reference to a registry value or an inlined, anonymous value.
|
||||
* <p>
|
||||
* Create with {@link RegistrySet#holderSetBuilder(RegistryKey)}, or if in a registry event context,
|
||||
* {@link io.papermc.paper.registry.event.RegistryFactory#createSetBuilder(RegistryKey)}.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the API type
|
||||
* @param <E> the registry entry type
|
||||
*/
|
||||
public non-sealed interface RegistryHolderSet<T extends RegistryElement.Buildable<T, E, ?>, E> extends RegistrySet<T> {
|
||||
|
||||
/**
|
||||
* Gets the holders in this set.
|
||||
*
|
||||
* @return an unmodifiable collection of holders
|
||||
*/
|
||||
@Unmodifiable Collection<RegistryHolder<T, E>> holders();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.papermc.paper.registry.set;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A builder for a {@link RegistryHolderSet}.
|
||||
*
|
||||
* @param <T> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
*/
|
||||
public interface RegistryHolderSetBuilder<T extends RegistryElement.Inlineable<T, E, B>, E, B extends RegistryBuilder<T>> {
|
||||
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param value the value to add
|
||||
* @return this builder
|
||||
*/
|
||||
RegistryHolderSetBuilder<T, E, B> add(T value);
|
||||
|
||||
/**
|
||||
* Adds a value by its key to the set. The referenced value does not need
|
||||
* to be present in the registry yet.
|
||||
*
|
||||
* @param key the key of the value to add
|
||||
* @return this builder
|
||||
*/
|
||||
RegistryHolderSetBuilder<T, E, B> add(TypedKey<T> key);
|
||||
|
||||
/**
|
||||
* Adds an inlined, anonymous value built from the given builder consumer to the set.
|
||||
*
|
||||
* @param value a consumer configuring the inlined value's builder
|
||||
* @return this builder
|
||||
*/
|
||||
RegistryHolderSetBuilder<T, E, B> add(Consumer<RegistryBuilderFactory<T, ? extends B>> value);
|
||||
|
||||
/**
|
||||
* Builds the holder set.
|
||||
*
|
||||
* @return a new holder set
|
||||
*/
|
||||
RegistryHolderSet<T, E> build();
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package io.papermc.paper.registry.set;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import org.bukkit.Keyed;
|
||||
@@ -43,12 +42,24 @@ public non-sealed interface RegistryKeySet<T extends Keyed> extends Iterable<Typ
|
||||
* Resolve this set into a collection of values. Prefer using
|
||||
* {@link #values()}.
|
||||
*
|
||||
* @param registry the registry to resolve the values from (must match {@link #registryKey()})
|
||||
* @param ignored the registry to resolve the values from (must match {@link #registryKey()})
|
||||
* @return the resolved values
|
||||
* @see RegistryKeySet#values()
|
||||
* @see Registry#getTagValues(TagKey)
|
||||
* @deprecated use {@link #resolve()}, the registry is not needed
|
||||
*/
|
||||
@Unmodifiable Collection<T> resolve(final Registry<T> registry);
|
||||
@Deprecated(since = "26.4", forRemoval = true)
|
||||
default @Unmodifiable Collection<T> resolve(final Registry<T> ignored) {
|
||||
return this.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve this set into a collection of values. Prefer using
|
||||
* {@link #values()}.
|
||||
*
|
||||
* @return the resolved values
|
||||
* @see RegistryKeySet#values()
|
||||
*/
|
||||
@Unmodifiable Collection<T> resolve();
|
||||
|
||||
/**
|
||||
* Checks if this set contains the value with the given key.
|
||||
|
||||
@@ -37,7 +37,8 @@ record RegistryKeySetImpl<T extends Keyed>(RegistryKey<T> registryKey, List<Type
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> resolve(final Registry<T> registry) {
|
||||
public Collection<T> resolve() {
|
||||
final Registry<T> registry = RegistryAccess.registryAccess().getRegistry(this.registryKey);
|
||||
final List<T> values = new ArrayList<>(this.values.size());
|
||||
for (final TypedKey<T> key : this.values) {
|
||||
final T value = registry.get(key.key());
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package io.papermc.paper.registry.set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import java.util.List;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
@@ -16,13 +19,30 @@ import org.jetbrains.annotations.Contract;
|
||||
* These are obtained via {@link org.bukkit.Registry#getTag(io.papermc.paper.registry.tag.TagKey)}.</li>
|
||||
* <li>{@link RegistryKeySet} which is a set of keys linked to values that are present in the registry. These are
|
||||
* created via {@link #keySet(RegistryKey, Iterable)} or {@link #keySetFromValues(RegistryKey, Iterable)}.</li>
|
||||
* <li>{@link RegistryValueSet} which is a set of values which are anonymous (don't have keys in the registry). These are
|
||||
* created via {@link #valueSet(RegistryKey, Iterable)}.</li>
|
||||
* <li>{@link RegistryHolderSet} which is a mixed set of values, some of which are anonymous (don't have keys in the registry). These are
|
||||
* created via {@link #holderSetBuilder(RegistryKey)}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <T> registry value type
|
||||
*/
|
||||
public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet {
|
||||
public sealed interface RegistrySet<T> permits RegistryHolderSet, RegistryKeySet, RegistryValueSet {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link RegistryHolderSet}, a mixed set of registry-backed
|
||||
* references and inlined, anonymous values.
|
||||
* <p>
|
||||
* In a registry event context, use {@link io.papermc.paper.registry.event.RegistryFactory#createSetBuilder(RegistryKey)} instead.
|
||||
*
|
||||
* @param registryKey the registry key for the type of these values
|
||||
* @return a new holder set builder
|
||||
* @param <T> the API type
|
||||
* @param <E> the registry entry type
|
||||
* @param <B> the builder type
|
||||
*/
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
static <T extends Keyed & RegistryElement.Inlineable<T, E, B>, E, B extends RegistryBuilder<T>> RegistryHolderSetBuilder<T, E, B> holderSetBuilder(final RegistryKey<T> registryKey) { // TODO remove Keyed
|
||||
return RegistrySetProvider.instance().registryHolderSetBuilder(registryKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RegistryValueSet} from anonymous values.
|
||||
@@ -32,8 +52,10 @@ public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet
|
||||
* @param values the values
|
||||
* @return a new registry set
|
||||
* @param <T> the type of the values
|
||||
* @deprecated Use {@link #holderSetBuilder(RegistryKey)}
|
||||
*/
|
||||
@Contract(value = "_, _ -> new", pure = true)
|
||||
@Deprecated(since = "26.3", forRemoval = true)
|
||||
static <T> RegistryValueSet<T> valueSet(final RegistryKey<T> registryKey, final Iterable<? extends T> values) {
|
||||
return RegistryValueSetImpl.create(registryKey, values);
|
||||
}
|
||||
@@ -41,7 +63,7 @@ public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet
|
||||
/**
|
||||
* Creates a {@link RegistryKeySet} from registry-backed values.
|
||||
* <p>All values provided <b>must</b> have keys in the given registry.
|
||||
* <!--For anonymous values, use {@link #valueSet(RegistryKey, Iterable)}--></p>
|
||||
* For anonymous values, use {@link #valueSet(RegistryKey, Iterable)}.</p>
|
||||
* <p>If references to actual objects are not available yet, use {@link #keySet(RegistryKey, Iterable)} to
|
||||
* create an equivalent {@link RegistryKeySet} using just {@link TypedKey TypedKeys}.</p>
|
||||
*
|
||||
@@ -57,7 +79,7 @@ public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a direct {@link RegistrySet} from {@link TypedKey TypedKeys}.
|
||||
* Creates a direct {@code RegistrySet} from {@link TypedKey TypedKeys}.
|
||||
*
|
||||
* @param registryKey the registry key for the owner of these keys
|
||||
* @param keys the keys for the values
|
||||
@@ -70,7 +92,22 @@ public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a direct {@link RegistrySet} from {@link TypedKey TypedKeys}.
|
||||
* Creates a non empty direct {@code RegistrySet} from {@link TypedKey TypedKeys}.
|
||||
*
|
||||
* @param firstKey the first key for the values
|
||||
* @param otherKeys the other keys for the values
|
||||
* @return a new registry set
|
||||
* @param <T> the type of the values
|
||||
*/
|
||||
@SafeVarargs
|
||||
static <T extends Keyed> RegistryKeySet<T> keySet(final TypedKey<T> firstKey, final TypedKey<T>... otherKeys) { // TODO remove Keyed
|
||||
final List<TypedKey<T>> keys = Lists.newArrayList(otherKeys);
|
||||
keys.addFirst(firstKey);
|
||||
return keySet(firstKey.registryKey(), keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a direct {@code RegistrySet} from {@link TypedKey TypedKeys}.
|
||||
*
|
||||
* @param registryKey the registry key for the owner of these keys
|
||||
* @param keys the keys for the values
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.papermc.paper.registry.set;
|
||||
|
||||
import io.papermc.paper.registry.RegistryBuilder;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import org.bukkit.Keyed;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@ApiStatus.NonExtendable
|
||||
public interface RegistrySetProvider {
|
||||
|
||||
static RegistrySetProvider instance() {
|
||||
final class Holder {
|
||||
static final Optional<RegistrySetProvider> INSTANCE = ServiceLoader.load(RegistrySetProvider.class, RegistrySetProvider.class.getClassLoader()).findFirst();
|
||||
}
|
||||
return Holder.INSTANCE.orElseThrow();
|
||||
}
|
||||
|
||||
<T extends Keyed & RegistryElement.Inlineable<T, E, B>, E, B extends RegistryBuilder<T>> RegistryHolderSetBuilder<T, E, B> registryHolderSetBuilder(RegistryKey<T> registryKey); // TODO remove Keyed
|
||||
}
|
||||
@@ -12,7 +12,9 @@ import org.jetbrains.annotations.Unmodifiable;
|
||||
* in the context of a {@link io.papermc.paper.registry.RegistryBuilder},
|
||||
* there are methods to create them like {@link DialogRegistryEntry.Builder#registryValueSet()}.
|
||||
* @param <T> registry value type
|
||||
* @deprecated use {@link RegistryHolderSet} and {@link RegistryHolderSetBuilder}
|
||||
*/
|
||||
@Deprecated(since = "26.4", forRemoval = true)
|
||||
public sealed interface RegistryValueSet<T> extends Iterable<T>, RegistrySet<T> permits RegistryValueSetImpl {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,8 +10,10 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
*
|
||||
* @param <API> the API type
|
||||
* @param <ENTRY_BUILDER> the type of the entry builder,
|
||||
* @deprecated use {@link RegistryHolderSetBuilder}
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
@Deprecated(since = "26.4", forRemoval = true)
|
||||
public interface RegistryValueSetBuilder<API, ENTRY_BUILDER extends RegistryBuilder<API>> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.papermc.paper.world.chunk;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* The generation state of a chunk, as reported by {@link World#getChunkGenerationState(int, int)}
|
||||
* and {@link World#getChunkGenerationStateAsync(int, int)}.
|
||||
*/
|
||||
public enum ChunkGenerationState {
|
||||
/**
|
||||
* The chunk is not loaded and has no saved data.
|
||||
*/
|
||||
NOT_GENERATED,
|
||||
/**
|
||||
* Generation of the chunk has started but has not completed. Loading the chunk
|
||||
* will complete generation.
|
||||
*/
|
||||
PARTIAL,
|
||||
/**
|
||||
* The chunk has saved data that must be upgraded before it can be loaded, for
|
||||
* example because it was saved by an older version, or it has pending world
|
||||
* generation from a world height change. Loading the chunk will modify it.
|
||||
*
|
||||
* <p>
|
||||
* The chunk may be partially or fully generated; generation progress is not
|
||||
* determined for chunks in this state, as doing so would require upgrading
|
||||
* the chunk data.
|
||||
* </p>
|
||||
*/
|
||||
OUTDATED,
|
||||
/**
|
||||
* The chunk is fully generated and up to date. Loading it will not change it.
|
||||
*/
|
||||
GENERATED
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Package for Chunk types.
|
||||
*/
|
||||
@NullMarked
|
||||
package io.papermc.paper.world.chunk;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -2,7 +2,9 @@ package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
@@ -18,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* There may be additional arts present in the server, for example from a {@link io.papermc.paper.datapack.Datapack}
|
||||
* which can be accessed via {@link RegistryAccess#registryAccess()} and {@link RegistryKey#PAINTING_VARIANT}.
|
||||
*/
|
||||
public interface Art extends OldEnum<Art>, Keyed {
|
||||
public interface Art extends RegistryElement.Buildable<Art, PaintingVariantRegistryEntry, PaintingVariantRegistryEntry.Builder>, OldEnum<Art>, Keyed {
|
||||
|
||||
// Start generate - Art
|
||||
Art ALBAN = getArt("alban");
|
||||
|
||||
@@ -961,8 +961,7 @@ public final class Bukkit {
|
||||
* Create a new explorer map targeting the closest nearby structure of a
|
||||
* given {@link StructureType}.
|
||||
* <br>
|
||||
* This method uses implementation default values for radius and
|
||||
* findUnexplored (usually 100, true).
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
@@ -986,8 +985,7 @@ public final class Bukkit {
|
||||
* Create a new explorer map targeting the closest nearby structure of a
|
||||
* given {@link org.bukkit.generator.structure.StructureType}.
|
||||
* <br>
|
||||
* This method uses implementation default values for radius and
|
||||
* findUnexplored (usually 100, true).
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
@@ -1021,6 +1019,45 @@ public final class Bukkit {
|
||||
public static @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored) {
|
||||
return server.createExplorerMap(world, location, structureType, mapIcon, radius, findUnexplored);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby specific
|
||||
* {@link org.bukkit.generator.structure.Structure}.
|
||||
* <br>
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
* @param structure the specific structure to find
|
||||
* @param mapIcon the map icon to use on the map
|
||||
* @return a newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.generator.structure.Structure, int, boolean)
|
||||
*/
|
||||
public static @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.Structure structure, @NotNull org.bukkit.map.MapCursor.Type mapIcon) {
|
||||
return server.createExplorerMap(world, location, structure, mapIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby specific
|
||||
* {@link org.bukkit.generator.structure.Structure}.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
* @param structure the specific structure to find
|
||||
* @param mapIcon the map icon to use on the map
|
||||
* @param radius radius to search, see World#locateNearestStructure for more
|
||||
* information
|
||||
* @param findUnexplored whether to find unexplored structures
|
||||
* @return the newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.generator.structure.Structure, int, boolean)
|
||||
*/
|
||||
public static @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.Structure structure, @NotNull org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored) {
|
||||
return server.createExplorerMap(world, location, structure, mapIcon, radius, findUnexplored);
|
||||
}
|
||||
// Paper end
|
||||
|
||||
/**
|
||||
@@ -1079,7 +1116,11 @@ public final class Bukkit {
|
||||
*
|
||||
* @param name the name of the command to retrieve
|
||||
* @return a plugin command if found, null otherwise
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended.
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
@Nullable
|
||||
public static PluginCommand getPluginCommand(@NotNull String name) {
|
||||
return server.getPluginCommand(name);
|
||||
@@ -1108,14 +1149,14 @@ public final class Bukkit {
|
||||
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
* Recipes added with this method won't be sent to the client automatically.
|
||||
* Recipes added with this method will be sent to the client automatically.
|
||||
* <p>
|
||||
* Players still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)}
|
||||
* before seeing them in their recipe book.
|
||||
*
|
||||
* @param recipe the recipe to add
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @see #addRecipe(Recipe, boolean)
|
||||
* @throws IllegalStateException if the recipe is already added to the crafting manager
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean addRecipe(@Nullable Recipe recipe) {
|
||||
@@ -1125,14 +1166,30 @@ public final class Bukkit {
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
*
|
||||
* @apiNote resendRecipes is ignored at the moment for stability reasons, recipes will always be updated
|
||||
* @param recipe the recipe to add
|
||||
* @param resendRecipes true to update the client with the full set of recipes
|
||||
* @param resendRecipes ignored, refer to the deprecation note
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @throws IllegalStateException if the recipe is already added to the crafting manager
|
||||
* @deprecated use {@link #addRecipe(Recipe)} instead, as Minecraft always resends recipes on a recipe added
|
||||
*/
|
||||
@Deprecated(since = "26.3")
|
||||
@Contract("null, _ -> false")
|
||||
public static boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes) {
|
||||
return server.addRecipe(recipe, resendRecipes);
|
||||
return server.addRecipe(recipe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple recipes to the crafting manager at once, resending recipes only once
|
||||
* after all have been added.
|
||||
*
|
||||
* @apiNote This method differs from {@link #addRecipe} in that it will only resend the recipe book once instead of once per every recipe added
|
||||
* @param recipes the recipes to add
|
||||
* @return true if any recipe was added, false if none were for some reason
|
||||
* @throws IllegalStateException if any of the recipes are already added to the crafting manager
|
||||
* @see #addRecipe
|
||||
*/
|
||||
public static boolean addRecipes(@NotNull Iterable<Recipe> recipes) {
|
||||
return server.addRecipes(recipes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1313,8 +1370,18 @@ public final class Bukkit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a recipe from the server.
|
||||
* Checks if the server has a recipe
|
||||
*
|
||||
* @param key NamespacedKey of recipe to check for
|
||||
* @return True if there is a recipe with a matching key
|
||||
*/
|
||||
public static boolean hasRecipe(@NotNull NamespacedKey key) {
|
||||
return server.hasRecipe(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a recipe from the server.
|
||||
* <br>
|
||||
* <b>Note that removing a recipe may cause permanent loss of data
|
||||
* associated with that recipe (eg whether it has been discovered by
|
||||
* players).</b>
|
||||
@@ -1326,7 +1393,6 @@ public final class Bukkit {
|
||||
return server.removeRecipe(key);
|
||||
}
|
||||
|
||||
// Paper start - method to resend recipes
|
||||
/**
|
||||
* Remove a recipe from the server.
|
||||
* <p>
|
||||
@@ -1335,14 +1401,26 @@ public final class Bukkit {
|
||||
* players).</b>
|
||||
*
|
||||
* @param key NamespacedKey of recipe to remove.
|
||||
* @param resendRecipes true to update all clients on the new recipe list.
|
||||
* Will only update if a recipe was actually removed
|
||||
* @param resendRecipes ignored, refer to the deprecation note
|
||||
* @return True if recipe was removed
|
||||
* @deprecated use {@link #removeRecipe(NamespacedKey)} instead, as Minecraft always resends recipes on recipe removal
|
||||
*/
|
||||
@Deprecated(since = "26.3")
|
||||
public static boolean removeRecipe(@NotNull NamespacedKey key, boolean resendRecipes) {
|
||||
return server.removeRecipe(key, resendRecipes);
|
||||
return server.removeRecipe(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove multiple recipes from the server.
|
||||
*
|
||||
* @apiNote This method differs from {@link #removeRecipe} in that it will only resend the recipe book once instead of once per every recipe removed
|
||||
* @param keys the NamespacedKeys of the recipes to remove
|
||||
* @return true if any recipe was removed, false if none were for some reason
|
||||
* @see #removeRecipe
|
||||
*/
|
||||
public static boolean removeRecipes(@NotNull Iterable<NamespacedKey> keys) {
|
||||
return server.removeRecipes(keys);
|
||||
}
|
||||
// Paper end - method to resend recipes
|
||||
|
||||
/**
|
||||
* Gets a list of command aliases defined in the server properties.
|
||||
@@ -2654,7 +2732,11 @@ public final class Bukkit {
|
||||
* Gets the active {@link org.bukkit.command.CommandMap}
|
||||
*
|
||||
* @return the active command map
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
@NotNull
|
||||
public static org.bukkit.command.CommandMap getCommandMap() {
|
||||
return server.getCommandMap();
|
||||
|
||||
@@ -6,10 +6,12 @@ import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import net.kyori.adventure.util.ARGBLike;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.SerializableAs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
/**
|
||||
* A container for a color palette. This class is immutable; the set methods
|
||||
@@ -17,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* but subject to change.
|
||||
*/
|
||||
@SerializableAs("Color")
|
||||
public final class Color implements ConfigurationSerializable {
|
||||
public final class Color implements ConfigurationSerializable, ARGBLike {
|
||||
private static final int BIT_MASK = 0xff;
|
||||
private static final int DEFAULT_ALPHA = 255;
|
||||
|
||||
@@ -122,7 +124,12 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @throws IllegalArgumentException if any value is strictly {@literal >255 or <0}
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromARGB(int alpha, int red, int green, int blue) throws IllegalArgumentException {
|
||||
public static Color fromARGB(
|
||||
final @Range(from = 0, to = 255) int alpha,
|
||||
final @Range(from = 0, to = 255) int red,
|
||||
final @Range(from = 0, to = 255) int green,
|
||||
final @Range(from = 0, to = 255) int blue
|
||||
) throws IllegalArgumentException {
|
||||
return new Color(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
@@ -136,7 +143,11 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @throws IllegalArgumentException if any value is strictly {@literal >255 or <0}
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromRGB(int red, int green, int blue) throws IllegalArgumentException {
|
||||
public static Color fromRGB(
|
||||
final @Range(from = 0, to = 255) int red,
|
||||
final @Range(from = 0, to = 255) int green,
|
||||
final @Range(from = 0, to = 255) int blue
|
||||
) throws IllegalArgumentException {
|
||||
return new Color(DEFAULT_ALPHA, red, green, blue);
|
||||
}
|
||||
|
||||
@@ -150,7 +161,11 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @throws IllegalArgumentException if any value is strictly {@literal >255 or <0}
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromBGR(int blue, int green, int red) throws IllegalArgumentException {
|
||||
public static Color fromBGR(
|
||||
final @Range(from = 0, to = 255) int blue,
|
||||
final @Range(from = 0, to = 255) int green,
|
||||
final @Range(from = 0, to = 255) int red
|
||||
) throws IllegalArgumentException {
|
||||
return new Color(DEFAULT_ALPHA, red, green, blue);
|
||||
}
|
||||
|
||||
@@ -164,7 +179,7 @@ public final class Color implements ConfigurationSerializable {
|
||||
* bits
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromRGB(int rgb) throws IllegalArgumentException {
|
||||
public static Color fromRGB(final int rgb) throws IllegalArgumentException {
|
||||
Preconditions.checkArgument((rgb >> 24) == 0, "Extraneous data in: %s", rgb);
|
||||
return fromRGB(rgb >> 16 & BIT_MASK, rgb >> 8 & BIT_MASK, rgb & BIT_MASK);
|
||||
}
|
||||
@@ -177,7 +192,7 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @return a new color object for specified values
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromARGB(int argb) {
|
||||
public static Color fromARGB(final int argb) {
|
||||
return fromARGB(argb >> 24 & BIT_MASK, argb >> 16 & BIT_MASK, argb >> 8 & BIT_MASK, argb & BIT_MASK);
|
||||
}
|
||||
|
||||
@@ -191,16 +206,16 @@ public final class Color implements ConfigurationSerializable {
|
||||
* bits
|
||||
*/
|
||||
@NotNull
|
||||
public static Color fromBGR(int bgr) throws IllegalArgumentException {
|
||||
public static Color fromBGR(final int bgr) throws IllegalArgumentException {
|
||||
Preconditions.checkArgument((bgr >> 24) == 0, "Extrenuous data in: %s", bgr);
|
||||
return fromBGR(bgr >> 16 & BIT_MASK, bgr >> 8 & BIT_MASK, bgr & BIT_MASK);
|
||||
}
|
||||
|
||||
private Color(int red, int green, int blue) {
|
||||
private Color(final int red, final int green, final int blue) {
|
||||
this(DEFAULT_ALPHA, red, green, blue);
|
||||
}
|
||||
|
||||
private Color(int alpha, int red, int green, int blue) {
|
||||
private Color(final int alpha, final int red, final int green, final int blue) {
|
||||
Preconditions.checkArgument(alpha >= 0 && alpha <= 0xff, "Alpha[%s] is not between 0-255", alpha);
|
||||
Preconditions.checkArgument(red >= 0 && red <= 0xff, "Red[%s] is not between 0-255", red);
|
||||
Preconditions.checkArgument(green >= 0 && green <= 0xff, "Green[%s] is not between 0-255", green);
|
||||
@@ -213,83 +228,123 @@ public final class Color implements ConfigurationSerializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the alpha component
|
||||
* Gets the alpha component.
|
||||
*
|
||||
* @return alpha component, from 0 to 255
|
||||
*/
|
||||
public int getAlpha() {
|
||||
public @Range(from = 0, to = 255) int getAlpha() {
|
||||
return BIT_MASK & alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
* Gets the alpha component.
|
||||
*
|
||||
* @return alpha component, from 0 to 255
|
||||
*/
|
||||
@Override
|
||||
public @Range(from = 0, to = 255) int alpha() {
|
||||
return this.getAlpha();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with a specified component.
|
||||
*
|
||||
* @param alpha the alpha component, from 0 to 255
|
||||
* @return a new color object with the alpha component
|
||||
*/
|
||||
@NotNull
|
||||
public Color setAlpha(int alpha) {
|
||||
return fromARGB(alpha, getRed(), getGreen(), getBlue());
|
||||
public Color setAlpha(final @Range(from = 0, to = 255) int alpha) {
|
||||
return fromARGB(alpha, this.getRed(), this.getGreen(), this.getBlue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the red component
|
||||
* Gets the red component.
|
||||
*
|
||||
* @return red component, from 0 to 255
|
||||
*/
|
||||
public int getRed() {
|
||||
return BIT_MASK & red;
|
||||
public @Range(from = 0, to = 255) int getRed() {
|
||||
return BIT_MASK & this.red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
* Gets the red component.
|
||||
*
|
||||
* @return red component, from 0 to 255
|
||||
*/
|
||||
@Override
|
||||
public @Range(from = 0, to = 255) int red() {
|
||||
return this.getRed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with a specified component.
|
||||
*
|
||||
* @param red the red component, from 0 to 255
|
||||
* @return a new color object with the red component
|
||||
*/
|
||||
@NotNull
|
||||
public Color setRed(int red) {
|
||||
return fromARGB(getAlpha(), red, getGreen(), getBlue());
|
||||
public Color setRed(final @Range(from = 0, to = 255) int red) {
|
||||
return fromARGB(this.getAlpha(), red, this.getGreen(), this.getBlue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the green component
|
||||
* Gets the green component.
|
||||
*
|
||||
* @return green component, from 0 to 255
|
||||
*/
|
||||
public int getGreen() {
|
||||
return BIT_MASK & green;
|
||||
public @Range(from = 0, to = 255) int getGreen() {
|
||||
return BIT_MASK & this.green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
* Gets the green component.
|
||||
*
|
||||
* @return green component, from 0 to 255
|
||||
*/
|
||||
@Override
|
||||
public @Range(from = 0, to = 255) int green() {
|
||||
return this.getGreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with a specified component.
|
||||
*
|
||||
* @param green the green component, from 0 to 255
|
||||
* @return a new color object with the green component
|
||||
*/
|
||||
@NotNull
|
||||
public Color setGreen(int green) {
|
||||
return fromARGB(getAlpha(), getRed(), green, getBlue());
|
||||
public Color setGreen(final @Range(from = 0, to = 255) int green) {
|
||||
return fromARGB(this.getAlpha(), this.getRed(), green, this.getBlue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blue component
|
||||
* Gets the blue component.
|
||||
*
|
||||
* @return blue component, from 0 to 255
|
||||
*/
|
||||
public int getBlue() {
|
||||
return BIT_MASK & blue;
|
||||
public @Range(from = 0, to = 255) int getBlue() {
|
||||
return BIT_MASK & this.blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
* Gets the blue component.
|
||||
*
|
||||
* @return blue component, from 0 to 255
|
||||
*/
|
||||
@Override
|
||||
public @Range(from = 0, to = 255) int blue() {
|
||||
return this.getBlue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with a specified component.
|
||||
*
|
||||
* @param blue the blue component, from 0 to 255
|
||||
* @return a new color object with the blue component
|
||||
*/
|
||||
@NotNull
|
||||
public Color setBlue(int blue) {
|
||||
return fromARGB(getAlpha(), getRed(), getGreen(), blue);
|
||||
public Color setBlue(final @Range(from = 0, to = 255) int blue) {
|
||||
return fromARGB(this.getAlpha(), this.getRed(), this.getGreen(), blue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,7 +353,7 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @return An integer representation of this color, as 0xRRGGBB
|
||||
*/
|
||||
public int asRGB() {
|
||||
return getRed() << 16 | getGreen() << 8 | getBlue();
|
||||
return this.getRed() << 16 | this.getGreen() << 8 | this.getBlue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,7 +362,7 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @return An integer representation of this color, as 0xAARRGGBB
|
||||
*/
|
||||
public int asARGB() {
|
||||
return getAlpha() << 24 | getRed() << 16 | getGreen() << 8 | getBlue();
|
||||
return this.getAlpha() << 24 | this.getRed() << 16 | this.getGreen() << 8 | this.getBlue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,33 +371,33 @@ public final class Color implements ConfigurationSerializable {
|
||||
* @return An integer representation of this color, as 0xBBGGRR
|
||||
*/
|
||||
public int asBGR() {
|
||||
return getBlue() << 16 | getGreen() << 8 | getRed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color with its RGB components changed as if it was dyed
|
||||
* with the colors passed in, replicating vanilla workbench dyeing
|
||||
*
|
||||
* @param colors The DyeColors to dye with
|
||||
* @return A new color with the changed rgb components
|
||||
*/
|
||||
// TODO: Javadoc what this method does, not what it mimics. API != Implementation
|
||||
@NotNull
|
||||
public Color mixDyes(@NotNull DyeColor... colors) {
|
||||
Preconditions.checkArgument(colors != null && Arrays.stream(colors).allMatch(Objects::nonNull), "DyeColor cannot be null or contain null values");
|
||||
|
||||
Color[] toPass = new Color[colors.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
toPass[i] = colors[i].getColor();
|
||||
}
|
||||
|
||||
return mixColors(toPass);
|
||||
return this.getBlue() << 16 | this.getGreen() << 8 | this.getRed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color with its RGB components changed as if it was dyed
|
||||
* with the colors passed in, replicating vanilla workbench dyeing.
|
||||
*
|
||||
* @param colors The DyeColors to dye with
|
||||
* @return A new color with the changed rgb components
|
||||
*/
|
||||
// TODO: Javadoc what this method does, not what it mimics. API != Implementation
|
||||
@NotNull
|
||||
public Color mixDyes(final @NotNull DyeColor... colors) {
|
||||
Preconditions.checkArgument(colors != null && Arrays.stream(colors).allMatch(Objects::nonNull), "DyeColor cannot be null or contain null values");
|
||||
|
||||
final Color[] toPass = new Color[colors.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
toPass[i] = colors[i].getColor();
|
||||
}
|
||||
|
||||
return this.mixColors(toPass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color with its RGB components changed as if it was dyed
|
||||
* with the colors passed in, replicating vanilla workbench dyeing.
|
||||
* <br>
|
||||
* <b>Note that this method does not currently take into account alpha
|
||||
* components.</b>
|
||||
*
|
||||
@@ -351,7 +406,7 @@ public final class Color implements ConfigurationSerializable {
|
||||
*/
|
||||
// TODO: Javadoc what this method does, not what it mimics. API != Implementation
|
||||
@NotNull
|
||||
public Color mixColors(@NotNull Color... colors) {
|
||||
public Color mixColors(final @NotNull Color... colors) {
|
||||
Preconditions.checkArgument(colors != null && Arrays.stream(colors).allMatch(Objects::nonNull), "Colors cannot be null");
|
||||
|
||||
int totalRed = this.getRed();
|
||||
@@ -365,44 +420,43 @@ public final class Color implements ConfigurationSerializable {
|
||||
totalMax += Math.max(Math.max(color.getRed(), color.getGreen()), color.getBlue());
|
||||
}
|
||||
|
||||
float averageRed = totalRed / (colors.length + 1);
|
||||
float averageGreen = totalGreen / (colors.length + 1);
|
||||
float averageBlue = totalBlue / (colors.length + 1);
|
||||
float averageMax = totalMax / (colors.length + 1);
|
||||
final float averageRed = totalRed / (colors.length + 1);
|
||||
final float averageGreen = totalGreen / (colors.length + 1);
|
||||
final float averageBlue = totalBlue / (colors.length + 1);
|
||||
final float averageMax = totalMax / (colors.length + 1);
|
||||
|
||||
float maximumOfAverages = Math.max(Math.max(averageRed, averageGreen), averageBlue);
|
||||
float gainFactor = averageMax / maximumOfAverages;
|
||||
final float maximumOfAverages = Math.max(Math.max(averageRed, averageGreen), averageBlue);
|
||||
final float gainFactor = averageMax / maximumOfAverages;
|
||||
|
||||
return Color.fromRGB((int) (averageRed * gainFactor), (int) (averageGreen * gainFactor), (int) (averageBlue * gainFactor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Color)) {
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof Color that)) {
|
||||
return false;
|
||||
}
|
||||
final Color that = (Color) o;
|
||||
return this.alpha == that.alpha && this.blue == that.blue && this.green == that.green && this.red == that.red;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return asARGB() ^ Color.class.hashCode();
|
||||
return this.asARGB() ^ Color.class.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<String, Object> serialize() {
|
||||
return ImmutableMap.of(
|
||||
"ALPHA", getAlpha(),
|
||||
"RED", getRed(),
|
||||
"BLUE", getBlue(),
|
||||
"GREEN", getGreen()
|
||||
"ALPHA", this.getAlpha(),
|
||||
"RED", this.getRed(),
|
||||
"BLUE", this.getBlue(),
|
||||
"GREEN", this.getGreen()
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Color deserialize(@NotNull Map<String, Object> map) {
|
||||
public static Color deserialize(final @NotNull Map<String, Object> map) {
|
||||
return fromARGB(
|
||||
asInt("ALPHA", map, DEFAULT_ALPHA),
|
||||
asInt("RED", map),
|
||||
@@ -411,23 +465,23 @@ public final class Color implements ConfigurationSerializable {
|
||||
);
|
||||
}
|
||||
|
||||
private static int asInt(@NotNull String string, @NotNull Map<String, Object> map) {
|
||||
private static int asInt(final @NotNull String string, final @NotNull Map<String, Object> map) {
|
||||
return asInt(string, map, null);
|
||||
}
|
||||
|
||||
private static int asInt(@NotNull String string, @NotNull Map<String, Object> map, @Nullable Object defaultValue) {
|
||||
Object value = map.getOrDefault(string, defaultValue);
|
||||
private static int asInt(final @NotNull String string, final @NotNull Map<String, Object> map, final @Nullable Object defaultValue) {
|
||||
final Object value = map.getOrDefault(string, defaultValue);
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException(string + " not in map " + map);
|
||||
}
|
||||
if (!(value instanceof Number)) {
|
||||
if (!(value instanceof Number number)) {
|
||||
throw new IllegalArgumentException(string + '(' + value + ") is not a number");
|
||||
}
|
||||
return ((Number) value).intValue();
|
||||
return number.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Color:[argb0x" + Integer.toHexString(asARGB()).toUpperCase(Locale.ROOT) + "]";
|
||||
return "Color:[argb0x" + Integer.toHexString(this.asARGB()).toUpperCase(Locale.ROOT) + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Represents a fluid type.
|
||||
*/
|
||||
public interface Fluid extends OldEnum<Fluid>, Keyed {
|
||||
public interface Fluid extends RegistryElement<Fluid>, OldEnum<Fluid>, Keyed {
|
||||
|
||||
// Start generate - Fluid
|
||||
Fluid EMPTY = getFluid("empty");
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.bukkit;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.data.GameEventRegistryEntry;
|
||||
import java.util.Collection;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
@@ -9,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a generic Mojang game event.
|
||||
*/
|
||||
public abstract class GameEvent implements Keyed {
|
||||
public abstract class GameEvent implements RegistryElement.Buildable<GameEvent, GameEventRegistryEntry, GameEventRegistryEntry.Builder>, Keyed {
|
||||
|
||||
// Start generate - GameEvent
|
||||
public static final GameEvent BLOCK_ACTIVATE = getEvent("block_activate");
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.world.flag.FeatureDependant;
|
||||
import java.util.function.UnaryOperator;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -19,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @see GameRules
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public abstract class GameRule<T> implements net.kyori.adventure.translation.Translatable, FeatureDependant, Keyed {
|
||||
public abstract class GameRule<T> implements RegistryElement<GameRule<T>>, net.kyori.adventure.translation.Translatable, FeatureDependant, Keyed {
|
||||
|
||||
// Boolean rules
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.bukkit;
|
||||
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.JukeboxSongRegistryEntry;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -11,7 +13,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
* Represents a song which may play in a Jukebox.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface JukeboxSong extends Keyed, Translatable {
|
||||
public interface JukeboxSong extends RegistryElement.Buildable<JukeboxSong, JukeboxSongRegistryEntry, JukeboxSongRegistryEntry.Builder>, Keyed, Translatable {
|
||||
|
||||
// Start generate - JukeboxSong
|
||||
JukeboxSong ELEVEN = get("11");
|
||||
|
||||
@@ -2,9 +2,10 @@ package org.bukkit;
|
||||
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.InlinedRegistryBuilderProvider;
|
||||
import io.papermc.paper.registry.data.InstrumentRegistryEntry;
|
||||
import io.papermc.paper.registry.data.RegistryBuilderProvider;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.key.Key;
|
||||
@@ -14,7 +15,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable {
|
||||
public abstract class MusicInstrument implements RegistryElement.Inlineable<MusicInstrument, InstrumentRegistryEntry, InstrumentRegistryEntry.Builder>, Keyed, net.kyori.adventure.translation.Translatable {
|
||||
|
||||
/**
|
||||
* Creates an inlined music instrument.
|
||||
@@ -23,7 +24,7 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran
|
||||
* @return the created music instrument
|
||||
*/
|
||||
public static MusicInstrument create(final Consumer<RegistryBuilderFactory<MusicInstrument, ? extends InstrumentRegistryEntry.Builder>> value) {
|
||||
return InlinedRegistryBuilderProvider.instance().createInstrument(value);
|
||||
return RegistryBuilderProvider.instance().create(RegistryKey.INSTRUMENT, value);
|
||||
}
|
||||
|
||||
// Start generate - MusicInstrument
|
||||
|
||||
@@ -500,7 +500,6 @@ 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)
|
||||
*/
|
||||
Tag<T> getTag(TagKey<T> key);
|
||||
|
||||
@@ -512,11 +511,13 @@ 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 #getTag(TagKey)
|
||||
* @see Tag#resolve(Registry)
|
||||
* @see Tag#resolve()
|
||||
* @deprecated use {@link Tag#resolve()} on the fetched tag
|
||||
*/
|
||||
@Deprecated(since = "26.4", forRemoval = true)
|
||||
default Collection<T> getTagValues(final TagKey<T> key) {
|
||||
Tag<T> tag = this.getTag(key);
|
||||
return tag.resolve(this);
|
||||
final Tag<T> tag = this.getTag(key);
|
||||
return tag.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,6 +61,8 @@ import org.bukkit.profile.PlayerProfile;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scoreboard.Criteria;
|
||||
import org.bukkit.scoreboard.ScoreboardManager;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.map.MapCursor;
|
||||
import org.bukkit.structure.StructureManager;
|
||||
import org.bukkit.util.CachedServerIcon;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -872,8 +874,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* Create a new explorer map targeting the closest nearby structure of a
|
||||
* given {@link StructureType}.
|
||||
* <br>
|
||||
* This method uses implementation default values for radius and
|
||||
* findUnexplored (usually 100, true).
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
@@ -882,9 +883,9 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.StructureType, int, boolean)
|
||||
* @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type)}
|
||||
* @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, MapCursor.Type)}
|
||||
*/
|
||||
@Deprecated // Paper
|
||||
@Deprecated
|
||||
@NotNull
|
||||
default ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType) {
|
||||
return this.createExplorerMap(world, location, structureType, 100, true);
|
||||
@@ -904,18 +905,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.StructureType, int, boolean)
|
||||
* @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, org.bukkit.map.MapCursor.Type, int, boolean)}
|
||||
* @deprecated use {@link #createExplorerMap(World, Location, org.bukkit.generator.structure.StructureType, MapCursor.Type, int, boolean)}
|
||||
*/
|
||||
@Deprecated // Paper
|
||||
@NotNull
|
||||
public ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType, int radius, boolean findUnexplored);
|
||||
// Paper start
|
||||
@Deprecated
|
||||
@NotNull ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType, int radius, boolean findUnexplored);
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby structure of a
|
||||
* given {@link org.bukkit.generator.structure.StructureType}.
|
||||
* given {@link StructureType}.
|
||||
* <br>
|
||||
* This method uses implementation default values for radius and
|
||||
* findUnexplored (usually 100, true).
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
@@ -924,15 +923,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @return a newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.generator.structure.StructureType, int, boolean)
|
||||
* StructureType, int, boolean)
|
||||
*/
|
||||
default @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon) {
|
||||
default @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull MapCursor.Type mapIcon) {
|
||||
return this.createExplorerMap(world, location, structureType, mapIcon, 100, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby structure of a
|
||||
* given {@link org.bukkit.generator.structure.StructureType}.
|
||||
* given {@link StructureType}.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
@@ -944,10 +943,46 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @return the newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* org.bukkit.generator.structure.StructureType, int, boolean)
|
||||
* StructureType, int, boolean)
|
||||
*/
|
||||
@Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored);
|
||||
// Paper end
|
||||
@Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull org.bukkit.generator.structure.StructureType structureType, @NotNull MapCursor.Type mapIcon, int radius, boolean findUnexplored);
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby specific
|
||||
* {@link Structure}.
|
||||
* <br>
|
||||
* This method uses a radius of 100 and only searches for unexplored structures.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
* @param structure the specific structure to find
|
||||
* @param mapIcon the map icon to use on the map
|
||||
* @return a newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* Structure, int, boolean)
|
||||
*/
|
||||
default @Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull Structure structure, @NotNull MapCursor.Type mapIcon) {
|
||||
return this.createExplorerMap(world, location, structure, mapIcon, 100, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new explorer map targeting the closest nearby specific
|
||||
* {@link Structure}.
|
||||
*
|
||||
* @param world the world the map will belong to
|
||||
* @param location the origin location to find the nearest structure
|
||||
* @param structure the specific structure to find
|
||||
* @param mapIcon the map icon to use on the map
|
||||
* @param radius radius to search, see World#locateNearestStructure for more
|
||||
* information
|
||||
* @param findUnexplored whether to find unexplored structures
|
||||
* @return the newly created item stack or null if it can't find a location
|
||||
*
|
||||
* @see World#locateNearestStructure(org.bukkit.Location,
|
||||
* Structure, int, boolean)
|
||||
*/
|
||||
@Nullable ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull Structure structure, @NotNull MapCursor.Type mapIcon, int radius, boolean findUnexplored);
|
||||
|
||||
/**
|
||||
* Reloads the server, refreshing settings and plugin information.
|
||||
@@ -995,7 +1030,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*
|
||||
* @param name the name of the command to retrieve
|
||||
* @return a plugin command if found, null otherwise
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
@Nullable
|
||||
public PluginCommand getPluginCommand(@NotNull String name);
|
||||
|
||||
@@ -1018,32 +1057,44 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
* Recipes added with this method won't be sent to the client automatically.
|
||||
* Recipes added with this method will be sent to the client automatically.
|
||||
* <p>
|
||||
* Players still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)}
|
||||
* before seeing them in their recipe book.
|
||||
*
|
||||
* @param recipe the recipe to add
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @see #addRecipe(Recipe, boolean)
|
||||
* @throws IllegalStateException if the recipe is already added to the crafting manager
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
default boolean addRecipe(@Nullable Recipe recipe) {
|
||||
return this.addRecipe(recipe, false);
|
||||
}
|
||||
boolean addRecipe(@Nullable Recipe recipe);
|
||||
|
||||
// Paper start - method to send recipes immediately
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
*
|
||||
* @apiNote resendRecipes is ignored for now for stability reasons, recipes will always be updated
|
||||
* @param recipe the recipe to add
|
||||
* @param resendRecipes true to update the client with the full set of recipes
|
||||
* @param resendRecipes ignored, refer to the deprecation note
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @throws IllegalStateException if the recipe is already added to the crafting manager
|
||||
* @deprecated use {@link #addRecipe(Recipe)} instead, as Minecraft always resends recipes on a recipe added
|
||||
*/
|
||||
@Deprecated(since = "26.3")
|
||||
@Contract("null, _ -> false")
|
||||
boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes);
|
||||
// Paper end - method to send recipes immediately
|
||||
default boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes) {
|
||||
return this.addRecipe(recipe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple recipes to the crafting manager at once, resending recipes only once
|
||||
* after all have been added.
|
||||
*
|
||||
* @apiNote This method differs from {@link #addRecipe} in that it will only resend the recipe book once instead of once per every recipe added
|
||||
* @param recipes the recipes to add
|
||||
* @return true if any recipe was added, false if none were for some reason
|
||||
* @throws IllegalStateException if any of the recipes are already added to the crafting manager
|
||||
* @see #addRecipe
|
||||
*/
|
||||
boolean addRecipes(@NotNull Iterable<Recipe> recipes);
|
||||
|
||||
/**
|
||||
* Get a list of all recipes for a given item. The stack size is ignored
|
||||
@@ -1205,6 +1256,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
public void resetRecipes();
|
||||
|
||||
/**
|
||||
* Checks if the server has a recipe
|
||||
*
|
||||
* @param key NamespacedKey of recipe to check for
|
||||
* @return True if there is a recipe with a matching key
|
||||
*/
|
||||
boolean hasRecipe(@NotNull NamespacedKey key);
|
||||
|
||||
/**
|
||||
* Remove a recipe from the server.
|
||||
*
|
||||
@@ -1215,11 +1274,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* @param key NamespacedKey of recipe to remove.
|
||||
* @return True if recipe was removed
|
||||
*/
|
||||
default boolean removeRecipe(@NotNull NamespacedKey key) {
|
||||
return this.removeRecipe(key, false);
|
||||
}
|
||||
boolean removeRecipe(@NotNull NamespacedKey key);
|
||||
|
||||
// Paper start - method to resend recipes
|
||||
/**
|
||||
* Remove a recipe from the server.
|
||||
* <p>
|
||||
@@ -1228,12 +1284,24 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* players).</b>
|
||||
*
|
||||
* @param key NamespacedKey of recipe to remove.
|
||||
* @param resendRecipes true to update all clients on the new recipe list.
|
||||
* Will only update if a recipe was actually removed
|
||||
* @param resendRecipes ignored, refer to the deprecation note
|
||||
* @return True if recipe was removed
|
||||
* @deprecated use {@link #removeRecipe(NamespacedKey)} instead, as Minecraft always resends recipes on recipe removal
|
||||
*/
|
||||
boolean removeRecipe(@NotNull NamespacedKey key, boolean resendRecipes);
|
||||
// Paper end - method to resend recipes
|
||||
@Deprecated(since = "26.3")
|
||||
default boolean removeRecipe(@NotNull NamespacedKey key, boolean resendRecipes) {
|
||||
return this.removeRecipe(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove multiple recipes from the server.
|
||||
*
|
||||
* @apiNote This method differs from {@link #removeRecipe} in that it will only resend the recipe book once instead of once per every recipe removed
|
||||
* @param keys the NamespacedKeys of the recipes to remove
|
||||
* @return true if any recipe was removed, false if none were for some reason
|
||||
* @see #removeRecipe
|
||||
*/
|
||||
boolean removeRecipes(@NotNull Iterable<NamespacedKey> keys);
|
||||
|
||||
/**
|
||||
* Gets a list of command aliases defined in the server properties.
|
||||
@@ -2207,7 +2275,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
* Gets the active {@link org.bukkit.command.CommandMap}
|
||||
*
|
||||
* @return the active command map
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
@NotNull
|
||||
org.bukkit.command.CommandMap getCommandMap();
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package org.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.registry.RegistryBuilderFactory;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.RegistryBuilderProvider;
|
||||
import io.papermc.paper.registry.data.SoundEventRegistryEntry;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import org.bukkit.util.OldEnum;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An interface of Sounds the server is able to send to players.
|
||||
@@ -21,7 +27,29 @@ import org.jetbrains.annotations.NotNull;
|
||||
* guarantee values will not be removed from this interface. As such, you should not
|
||||
* depend on the ordinal values of this class.
|
||||
*/
|
||||
public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type
|
||||
@NullMarked
|
||||
public interface Sound extends RegistryElement.Inlineable<Sound, SoundEventRegistryEntry, SoundEventRegistryEntry.Builder>, OldEnum<Sound>, Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type
|
||||
|
||||
/**
|
||||
* Creates an inlined sound event.
|
||||
*
|
||||
* @param key the sound location
|
||||
* @param range an optional fixed range
|
||||
* @return the created sound
|
||||
*/
|
||||
static Sound create(final Key key, final @Nullable Float range) {
|
||||
return create(builder -> builder.empty().location(key).fixedRange(range));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an inlined sound event.
|
||||
*
|
||||
* @param value a consumer for the builder factory
|
||||
* @return the created sound
|
||||
*/
|
||||
static Sound create(final Consumer<RegistryBuilderFactory<Sound, ? extends SoundEventRegistryEntry.Builder>> value) {
|
||||
return RegistryBuilderProvider.instance().create(RegistryKey.SOUND_EVENT, value);
|
||||
}
|
||||
|
||||
// Start generate - Sound
|
||||
Sound AMBIENT_BASALT_DELTAS_ADDITIONS = getSound("ambient.basalt_deltas.additions");
|
||||
@@ -4007,8 +4035,7 @@ public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.
|
||||
Sound WEATHER_RAIN_ABOVE = getSound("weather.rain.above");
|
||||
// End generate - Sound
|
||||
|
||||
@NotNull
|
||||
private static Sound getSound(@NotNull @KeyPattern.Value String key) {
|
||||
private static Sound getSound(@KeyPattern.Value String key) {
|
||||
return Registry.SOUNDS.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||
}
|
||||
|
||||
@@ -4017,9 +4044,8 @@ public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.
|
||||
* @return the sound with the given name.
|
||||
* @deprecated only for backwards compatibility, use {@link Registry#get(NamespacedKey)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "1.21.3", forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.22") // Paper - will be removed via asm-utils
|
||||
static Sound valueOf(@NotNull String name) {
|
||||
static Sound valueOf(String name) {
|
||||
final NamespacedKey key = NamespacedKey.fromString(name.toLowerCase(Locale.ROOT));
|
||||
Sound sound;
|
||||
|
||||
@@ -4049,14 +4075,21 @@ public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.
|
||||
*/
|
||||
@Deprecated(since = "1.20.5", forRemoval = true)
|
||||
@Override
|
||||
@NotNull NamespacedKey getKey();
|
||||
NamespacedKey getKey();
|
||||
// Paper end - deprecate getKey
|
||||
|
||||
/**
|
||||
* Gets the fixed range, a radius in block which this sound is audible.
|
||||
* The computed range will depends on the volume when this value is not defined.
|
||||
*
|
||||
* @return the fixed range
|
||||
*/
|
||||
@Nullable Float getFixedRange();
|
||||
|
||||
/**
|
||||
* @return an array of all known sounds.
|
||||
* @deprecated use {@link Registry#stream()}.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "1.21.3", forRemoval = true) @org.jetbrains.annotations.ApiStatus.ScheduledForRemoval(inVersion = "1.22") // Paper - will be removed via asm-utils
|
||||
static Sound[] values() {
|
||||
return Registry.SOUNDS.stream().toArray(Sound[]::new);
|
||||
@@ -4069,7 +4102,7 @@ public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.
|
||||
*/
|
||||
@Deprecated(since = "1.20.5", forRemoval = true)
|
||||
@Override
|
||||
default net.kyori.adventure.key.@NotNull Key key() {
|
||||
default net.kyori.adventure.key.Key key() {
|
||||
return this.getKey();
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@@ -110,7 +110,15 @@ public enum TreeType {
|
||||
*/
|
||||
PALE_OAK_CREAKING,
|
||||
/**
|
||||
* Poplar tree
|
||||
* Poplar tree with red leaves
|
||||
*/
|
||||
POPLAR,
|
||||
RED_POPLAR,
|
||||
/**
|
||||
* Poplar tree with orange leaves
|
||||
*/
|
||||
ORANGE_POPLAR,
|
||||
/**
|
||||
* Poplar tree with yellow leaves
|
||||
*/
|
||||
YELLOW_POPLAR,
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import io.papermc.paper.entity.poi.PoiSearchResult;
|
||||
import io.papermc.paper.entity.poi.PoiType;
|
||||
import io.papermc.paper.math.Position;
|
||||
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
|
||||
import io.papermc.paper.world.chunk.ChunkGenerationState;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -12,6 +13,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import org.bukkit.block.Biome;
|
||||
@@ -394,6 +396,58 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
||||
*/
|
||||
public boolean isChunkGenerated(int x, int z);
|
||||
|
||||
/**
|
||||
* Checks the generation state of the {@link Chunk} at the specified coordinates
|
||||
* without loading it, blocking until the state is known.
|
||||
*
|
||||
* <p>
|
||||
* This may read chunk data from disk, which blocks the calling thread. Prefer
|
||||
* {@link #getChunkGenerationStateAsync(int, int)} where possible.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The result is a snapshot: the chunk may be generated, loaded, or saved
|
||||
* concurrently, so the state may be stale by the time it is observed.
|
||||
* </p>
|
||||
*
|
||||
* @param x X-coordinate of the chunk
|
||||
* @param z Z-coordinate of the chunk
|
||||
* @return the generation state of the chunk
|
||||
* @throws RuntimeException if the chunk data cannot be read, or if it was saved
|
||||
* by a newer version of the game
|
||||
*/
|
||||
@NotNull ChunkGenerationState getChunkGenerationState(int x, int z);
|
||||
|
||||
/**
|
||||
* Checks the generation state of the {@link Chunk} at the specified coordinates
|
||||
* without loading it.
|
||||
*
|
||||
* <p>
|
||||
* The result is a snapshot: the chunk may be generated, loaded, or saved
|
||||
* concurrently, so the state may be stale by the time it is observed.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The returned future is completed on an unspecified thread. Callers that need to
|
||||
* interact with the world should move to the appropriate thread themselves.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If the main thread will block on the result, use {@link #getChunkGenerationState(int, int)}
|
||||
* instead, which reads the chunk data at a priority suitable for blocking.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The future is completed exceptionally if the chunk data cannot be read, or if
|
||||
* it was saved by a newer version of the game.
|
||||
* </p>
|
||||
*
|
||||
* @param x X-coordinate of the chunk
|
||||
* @param z Z-coordinate of the chunk
|
||||
* @return a future completed with the generation state of the chunk
|
||||
*/
|
||||
@NotNull CompletableFuture<@NotNull ChunkGenerationState> getChunkGenerationStateAsync(int x, int z);
|
||||
|
||||
/**
|
||||
* Checks if the {@link Chunk} at the specified coordinates is loaded and
|
||||
* in use by one or more players
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.bukkit.attribute;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
@@ -17,7 +18,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Types of attributes which may be present on an {@link Attributable}.
|
||||
*/
|
||||
public interface Attribute extends OldEnum<Attribute>, Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
|
||||
public interface Attribute extends RegistryElement<Attribute>, OldEnum<Attribute>, Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
|
||||
|
||||
/**
|
||||
* Maximum health of an Entity.
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.bukkit.block;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.InternalAPIBridge;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
@@ -23,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* There may be additional biomes present in the server, for example from a {@link io.papermc.paper.datapack.Datapack}
|
||||
* which can be accessed via {@link io.papermc.paper.registry.RegistryAccess#getRegistry(RegistryKey)} and {@link RegistryKey#BIOME}.
|
||||
*/
|
||||
public interface Biome extends OldEnum<Biome>, Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
|
||||
public interface Biome extends RegistryElement<Biome>, OldEnum<Biome>, Keyed, net.kyori.adventure.translation.Translatable { // Paper - Adventure translations
|
||||
|
||||
// Start generate - Biome
|
||||
Biome BADLANDS = getBiome("badlands");
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
import org.bukkit.Instrument;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
@@ -134,7 +136,7 @@ import org.jspecify.annotations.Nullable;
|
||||
* Represents a block type.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface BlockType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add translatable & feature flag API
|
||||
public interface BlockType extends RegistryElement<BlockType>, Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add translatable & feature flag API
|
||||
|
||||
/**
|
||||
* Typed represents a subtype of {@link BlockType}s that have a known block
|
||||
@@ -2986,4 +2988,12 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
||||
* @return false if this block never has collision, true if it <b>might</b> have collision
|
||||
*/
|
||||
boolean hasCollision();
|
||||
|
||||
/**
|
||||
* Gets the {@link Instrument} associated with this block.
|
||||
* This determines the instrument sound that would be played if a Note Block were placed directly above or below this block.
|
||||
*
|
||||
* @return the associated instrument
|
||||
*/
|
||||
Instrument getInstrument();
|
||||
}
|
||||
@@ -1,27 +1,34 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
import io.papermc.paper.math.Position;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.block.sign.SignSide;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.material.Colorable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a captured state of either a SignPost or a WallSign.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface Sign extends TileState, Colorable {
|
||||
// Paper start
|
||||
|
||||
/**
|
||||
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
|
||||
*
|
||||
* @return List of components containing each line of text
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public java.util.List<net.kyori.adventure.text.Component> lines();
|
||||
@Deprecated(since = "1.20")
|
||||
default List<Component> lines() {
|
||||
return this.getSide(Side.FRONT).lines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line of text at the specified index on the {@link Side#FRONT}.
|
||||
@@ -29,13 +36,14 @@ public interface Sign extends TileState, Colorable {
|
||||
* For example, getLine(0) will return the first line of text.
|
||||
*
|
||||
* @param index Line number to get the text from, starting at 0
|
||||
* @throws IndexOutOfBoundsException Thrown when the line does not exist
|
||||
* @return Text on the given line
|
||||
* @throws IndexOutOfBoundsException Thrown when the line does not exist
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException;
|
||||
@Deprecated(since = "1.20")
|
||||
default Component line(int index) throws IndexOutOfBoundsException {
|
||||
return this.getSide(Side.FRONT).line(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line of text at the specified index on the {@link Side#FRONT}.
|
||||
@@ -44,23 +52,25 @@ public interface Sign extends TileState, Colorable {
|
||||
* "Line One".
|
||||
*
|
||||
* @param index Line number to set the text at, starting from 0
|
||||
* @param line New text to set at the specified index
|
||||
* @param line New text to set at the specified index
|
||||
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, Component)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException;
|
||||
// Paper end
|
||||
@Deprecated(since = "1.20")
|
||||
default void line(int index, Component line) throws IndexOutOfBoundsException {
|
||||
this.getSide(Side.FRONT).line(index, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
|
||||
*
|
||||
* @return Array of Strings containing each line of text
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
|
||||
*/
|
||||
@Deprecated(since = "1.20")
|
||||
@NotNull
|
||||
public String[] getLines();
|
||||
default String[] getLines() {
|
||||
return this.getSide(Side.FRONT).getLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line of text at the specified index.
|
||||
@@ -73,8 +83,9 @@ public interface Sign extends TileState, Colorable {
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
|
||||
*/
|
||||
@Deprecated(since = "1.20")
|
||||
@NotNull
|
||||
public String getLine(int index) throws IndexOutOfBoundsException;
|
||||
default String getLine(int index) throws IndexOutOfBoundsException {
|
||||
return this.getSide(Side.FRONT).getLine(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line of text at the specified index.
|
||||
@@ -83,12 +94,14 @@ public interface Sign extends TileState, Colorable {
|
||||
* "Line One".
|
||||
*
|
||||
* @param index Line number to set the text at, starting from 0
|
||||
* @param line New text to set at the specified index
|
||||
* @param line New text to set at the specified index
|
||||
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
|
||||
*/
|
||||
@Deprecated(since = "1.20")
|
||||
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
|
||||
default void setLine(int index, String line) throws IndexOutOfBoundsException {
|
||||
this.getSide(Side.FRONT).setLine(index, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks whether this sign can be edited by players.
|
||||
@@ -97,7 +110,9 @@ public interface Sign extends TileState, Colorable {
|
||||
* @deprecated use {@link #isWaxed()} instead
|
||||
*/
|
||||
@Deprecated(since = "1.20.1")
|
||||
public boolean isEditable();
|
||||
default boolean isEditable() {
|
||||
return !this.isWaxed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks whether this sign can be edited by players.
|
||||
@@ -106,7 +121,9 @@ public interface Sign extends TileState, Colorable {
|
||||
* @deprecated use {@link #setWaxed(boolean)} instead
|
||||
*/
|
||||
@Deprecated(since = "1.20.1")
|
||||
public void setEditable(boolean editable);
|
||||
default void setEditable(boolean editable) {
|
||||
this.setWaxed(!editable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not this sign has been waxed. If a sign has been waxed, it
|
||||
@@ -114,7 +131,7 @@ public interface Sign extends TileState, Colorable {
|
||||
*
|
||||
* @return if this sign is waxed
|
||||
*/
|
||||
public boolean isWaxed();
|
||||
boolean isWaxed();
|
||||
|
||||
/**
|
||||
* Sets whether or not this sign has been waxed. If a sign has been waxed, it
|
||||
@@ -122,7 +139,7 @@ public interface Sign extends TileState, Colorable {
|
||||
*
|
||||
* @param waxed if this sign is waxed
|
||||
*/
|
||||
public void setWaxed(boolean waxed);
|
||||
void setWaxed(boolean waxed);
|
||||
|
||||
/**
|
||||
* Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
|
||||
@@ -131,7 +148,9 @@ public interface Sign extends TileState, Colorable {
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#isGlowingText()}.
|
||||
*/
|
||||
@Deprecated(since = "1.20")
|
||||
public boolean isGlowingText();
|
||||
default boolean isGlowingText() {
|
||||
return this.getSide(Side.FRONT).isGlowingText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}.
|
||||
@@ -140,17 +159,20 @@ public interface Sign extends TileState, Colorable {
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setGlowingText(boolean)}.
|
||||
*/
|
||||
@Deprecated(since = "1.20")
|
||||
public void setGlowingText(boolean glowing);
|
||||
default void setGlowingText(boolean glowing) {
|
||||
this.getSide(Side.FRONT).setGlowingText(glowing);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#getColor()}.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated(since = "1.20")
|
||||
public DyeColor getColor();
|
||||
default @Nullable DyeColor getColor() {
|
||||
return this.getSide(Side.FRONT).getColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@@ -159,7 +181,9 @@ public interface Sign extends TileState, Colorable {
|
||||
*/
|
||||
@Override
|
||||
@Deprecated(since = "1.20")
|
||||
public void setColor(@NotNull DyeColor color);
|
||||
default void setColor(DyeColor color) {
|
||||
this.getSide(Side.FRONT).setColor(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the side of the sign.
|
||||
@@ -167,8 +191,7 @@ public interface Sign extends TileState, Colorable {
|
||||
* @param side the side of the sign
|
||||
* @return the selected side of the sign
|
||||
*/
|
||||
@NotNull
|
||||
public SignSide getSide(@NotNull Side side);
|
||||
SignSide getSide(Side side);
|
||||
|
||||
/**
|
||||
* Gets the side of this sign the given player is currently standing on.
|
||||
@@ -176,8 +199,7 @@ public interface Sign extends TileState, Colorable {
|
||||
* @param player the player
|
||||
* @return the side the player is standing on
|
||||
*/
|
||||
@NotNull
|
||||
public SignSide getTargetSide(@NotNull Player player);
|
||||
SignSide getTargetSide(Player player);
|
||||
|
||||
/**
|
||||
* Gets the player that is currently allowed to edit this sign. <br>
|
||||
@@ -187,16 +209,15 @@ public interface Sign extends TileState, Colorable {
|
||||
*
|
||||
* @return the player allowed to edit this sign, or null
|
||||
*/
|
||||
@Nullable
|
||||
public Player getAllowedEditor();
|
||||
// Paper start - More Sign Block API
|
||||
@Nullable Player getAllowedEditor();
|
||||
|
||||
/**
|
||||
* Gets the allowed editor's UUID.
|
||||
* <br>Edits from other players will be rejected if this value is not null.
|
||||
*
|
||||
* @return the allowed editor's UUID, or null
|
||||
*/
|
||||
@Nullable java.util.UUID getAllowedEditorUniqueId();
|
||||
@Nullable UUID getAllowedEditorUniqueId();
|
||||
|
||||
/**
|
||||
* Sets the allowed editor's UUID.
|
||||
@@ -205,7 +226,7 @@ public interface Sign extends TileState, Colorable {
|
||||
*
|
||||
* @param uuid the allowed editor's UUID
|
||||
*/
|
||||
void setAllowedEditorUniqueId(@Nullable java.util.UUID uuid);
|
||||
void setAllowedEditorUniqueId(@Nullable UUID uuid);
|
||||
|
||||
/**
|
||||
* Compute the side facing the specified entity.
|
||||
@@ -213,7 +234,7 @@ public interface Sign extends TileState, Colorable {
|
||||
* @param entity the entity
|
||||
* @return the side it is facing
|
||||
*/
|
||||
default @NotNull Side getInteractableSideFor(org.bukkit.entity.@NotNull Entity entity) {
|
||||
default Side getInteractableSideFor(final Entity entity) {
|
||||
return this.getInteractableSideFor(entity.getLocation());
|
||||
}
|
||||
|
||||
@@ -223,7 +244,7 @@ public interface Sign extends TileState, Colorable {
|
||||
* @param position the position
|
||||
* @return the side the position is facing
|
||||
*/
|
||||
default @NotNull Side getInteractableSideFor(io.papermc.paper.math.@NotNull Position position) {
|
||||
default Side getInteractableSideFor(final Position position) {
|
||||
return this.getInteractableSideFor(position.x(), position.z());
|
||||
}
|
||||
|
||||
@@ -234,6 +255,20 @@ public interface Sign extends TileState, Colorable {
|
||||
* @param z the z coord
|
||||
* @return the side the coordinates are facing
|
||||
*/
|
||||
@NotNull Side getInteractableSideFor(double x, double z);
|
||||
// Paper end - More Sign Block API
|
||||
Side getInteractableSideFor(double x, double z);
|
||||
|
||||
/**
|
||||
* Gets whether operator features are allowed on this sign.
|
||||
* When enabled, supported click events in the root component of each line are executed when the relevant side is used.
|
||||
*
|
||||
* @return if operator features are allowed
|
||||
*/
|
||||
boolean isOperatorFeaturesAllowed();
|
||||
|
||||
/**
|
||||
* Sets whether operator features are allowed on this sign.
|
||||
*
|
||||
* @param allowed whether operator features are allowed
|
||||
*/
|
||||
void setOperatorFeaturesAllowed(boolean allowed);
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package org.bukkit.block.banner;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryElement;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.KeyPattern;
|
||||
@@ -14,7 +16,7 @@ import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PatternType extends OldEnum<PatternType>, Keyed {
|
||||
public interface PatternType extends RegistryElement.Buildable<PatternType, BannerPatternRegistryEntry, BannerPatternRegistryEntry.Builder>, OldEnum<PatternType>, Keyed {
|
||||
|
||||
// Start generate - PatternType
|
||||
PatternType BASE = getType("base");
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.bukkit.block.data;
|
||||
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* A marker interface for block data that is both {@link FaceAttachable} and {@link Directional}.
|
||||
* <p>
|
||||
* This represents blocks that are mounted on a specific face of another block (e.g., buttons, levers)
|
||||
* and also have a facing direction.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface AttachableDirectional extends FaceAttachable, Directional {
|
||||
|
||||
/**
|
||||
* Gets the {@link BlockFace} of the block that this block is physically attached to.
|
||||
* This is determined by the attached face.
|
||||
* @return the block face to which this block is attached
|
||||
*/
|
||||
default BlockFace getAttachedBlockFace() {
|
||||
return switch (this.getAttachedFace()) {
|
||||
case FLOOR -> BlockFace.DOWN;
|
||||
case CEILING -> BlockFace.UP;
|
||||
case WALL -> this.getFacing().getOppositeFace();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import org.bukkit.block.PistonMoveReaction;
|
||||
import org.bukkit.block.structure.Mirror;
|
||||
import org.bukkit.block.structure.StructureRotation;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.bukkit.block.data.type;
|
||||
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.FaceAttachable;
|
||||
import org.bukkit.block.data.AttachableDirectional;
|
||||
|
||||
public interface Grindstone extends Directional, FaceAttachable {
|
||||
public interface Grindstone extends AttachableDirectional {
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package org.bukkit.block.data.type;
|
||||
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.FaceAttachable;
|
||||
import org.bukkit.block.data.AttachableDirectional;
|
||||
import org.bukkit.block.data.Powerable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface Switch extends Directional, FaceAttachable, Powerable {
|
||||
public interface Switch extends AttachableDirectional, Powerable {
|
||||
|
||||
@NotNull
|
||||
AttachedFace getAttachedFace();
|
||||
|
||||
@@ -15,12 +15,18 @@ import org.bukkit.entity.minecart.CommandMinecart;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.util.StringUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a Command, which executes various tasks upon user input
|
||||
*
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
public abstract class Command {
|
||||
private String name;
|
||||
private String nextLabel;
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package org.bukkit.command;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a class which contains a single method for executing commands
|
||||
*
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
public interface CommandExecutor {
|
||||
|
||||
/**
|
||||
@@ -18,6 +24,10 @@ public interface CommandExecutor {
|
||||
* @param label Alias of the command which was used
|
||||
* @param args Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args);
|
||||
}
|
||||
@@ -2,9 +2,16 @@ package org.bukkit.command;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
public interface CommandMap {
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,15 @@ import java.util.regex.Pattern; // Paper
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @apiNote plugin developers should prefer to use the
|
||||
* <a href="https://docs.papermc.io/paper/dev/command-api/basics/introduction/">Brigadier command API</a>.
|
||||
* For a direct alternative to Bukkit commands, <a href="https://docs.papermc.io/paper/dev/command-api/misc/basic-command/">Basic commands</a> are recommended
|
||||
*/
|
||||
@ApiStatus.Obsolete(since = "26.3")
|
||||
public class FormattedCommandAlias extends Command {
|
||||
private final String[] formatStrings;
|
||||
|
||||
|
||||
Loaded 100 of 477 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user