mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-01-03 17:52:15 +01:00
Merge branch 'master' into feature/new-custom-entity-api
This commit is contained in:
commit
086431573b
632 changed files with 62218 additions and 53249 deletions
71
.github/workflows/build.yml
vendored
71
.github/workflows/build.yml
vendored
|
@ -3,10 +3,12 @@ name: Build
|
|||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'gh-readonly-queue/**'
|
||||
paths-ignore:
|
||||
- '.github/ISSUE_TEMPLATE/*.yml'
|
||||
- '.github/actions/pullrequest.yml'
|
||||
- '.idea/copyright/*.xml'
|
||||
- '.idea/copyright/*.xml'
|
||||
- '.gitignore'
|
||||
- 'CONTRIBUTING.md'
|
||||
- 'LICENSE'
|
||||
|
@ -19,70 +21,82 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository and submodules
|
||||
uses: actions/checkout@v3
|
||||
# See https://github.com/actions/checkout/commits
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
# See https://github.com/gradle/wrapper-validation-action/commits
|
||||
uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
# See https://github.com/actions/setup-java/commits
|
||||
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: temurin
|
||||
|
||||
- name: Build
|
||||
uses: gradle/gradle-build-action@v2
|
||||
# See https://github.com/gradle/gradle-build-action/commits
|
||||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits
|
||||
with:
|
||||
arguments: build
|
||||
gradle-home-cache-cleanup: true
|
||||
|
||||
- name: Archive artifacts (Geyser Fabric)
|
||||
uses: actions/upload-artifact@v3
|
||||
# See https://github.com/actions/upload-artifact/commits
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Fabric
|
||||
path: bootstrap/fabric/build/libs/Geyser-Fabric.jar
|
||||
path: bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser NeoForge)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser NeoForge
|
||||
path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Standalone)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Standalone
|
||||
path: bootstrap/standalone/build/libs/Geyser-Standalone.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Spigot)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Spigot
|
||||
path: bootstrap/spigot/build/libs/Geyser-Spigot.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser BungeeCord)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser BungeeCord
|
||||
path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Sponge)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Sponge
|
||||
path: bootstrap/sponge/build/libs/Geyser-Sponge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Velocity)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Velocity
|
||||
path: bootstrap/velocity/build/libs/Geyser-Velocity.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser ViaProxy)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser ViaProxy
|
||||
path: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Publish to Maven Repository
|
||||
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
|
||||
uses: gradle/gradle-build-action@v2
|
||||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
|
||||
env:
|
||||
ORG_GRADLE_PROJECT_geysermcUsername: ${{ vars.DEPLOY_USER }}
|
||||
ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }}
|
||||
|
@ -108,23 +122,34 @@ jobs:
|
|||
ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$project/$GITHUB_RUN_NUMBER/"
|
||||
# Copy over artifacts
|
||||
rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/
|
||||
rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/mod/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/
|
||||
# Run the build script
|
||||
# Push the metadata
|
||||
echo "{\"project\": \"$project\", \"version\": \"$version\", \"id\": $GITHUB_RUN_NUMBER, \"commit\": \"$GITHUB_SHA\"}" > metadata.json
|
||||
rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$project/$GITHUB_RUN_NUMBER/
|
||||
|
||||
- name: Publish to Modrinth
|
||||
uses: gradle/gradle-build-action@v2
|
||||
- name: Publish to Modrinth (Fabric)
|
||||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
|
||||
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
with:
|
||||
arguments: fabric:modrinth
|
||||
gradle-home-cache-cleanup: true
|
||||
|
||||
|
||||
- name: Publish to Modrinth (NeoForge)
|
||||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
|
||||
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
with:
|
||||
arguments: neoforge:modrinth
|
||||
gradle-home-cache-cleanup: true
|
||||
|
||||
- name: Notify Discord
|
||||
if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }}
|
||||
uses: Tim203/actions-git-discord-webhook@main
|
||||
# See https://github.com/Tim203/actions-git-discord-webhook/commits
|
||||
uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff
|
||||
with:
|
||||
webhook_url: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
status: ${{ job.status }}
|
||||
|
|
62
.github/workflows/pullrequest.yml
vendored
62
.github/workflows/pullrequest.yml
vendored
|
@ -2,28 +2,22 @@ name: Build Pull Request
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.github/ISSUE_TEMPLATE/*.yml'
|
||||
- '.idea/copyright/*.xml'
|
||||
- '.gitignore'
|
||||
- 'CONTRIBUTING.md'
|
||||
- 'LICENSE'
|
||||
- 'Jenkinsfile '
|
||||
- 'README.md'
|
||||
- 'licenseheader.txt'
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v1
|
||||
# See https://github.com/actions/setup-java/commits
|
||||
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: temurin
|
||||
|
||||
- name: Check if the author has forked the API repo
|
||||
uses: Kas-tle/ForkFinder@v1.0.1
|
||||
# See https://github.com/Kas-tle/find-forks-action/commits
|
||||
uses: Kas-tle/find-forks-action@1b5447d1e3c7a8ed79583dd817cc5399686eed3a
|
||||
id: find_forks
|
||||
with:
|
||||
owner: GeyserMC
|
||||
|
@ -31,7 +25,7 @@ jobs:
|
|||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Use author's API repo if it exists
|
||||
if: steps.find_forks.outputs.target_branch_found == 'true'
|
||||
if: ${{ steps.find_forks.outputs.target_branch_found == 'true' }}
|
||||
env:
|
||||
API_FORK_URL: ${{ steps.find_forks.outputs.user_fork_url }}
|
||||
API_FORK_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
|
@ -41,56 +35,70 @@ jobs:
|
|||
./gradlew publishToMavenLocal
|
||||
|
||||
- name: Checkout repository and submodules
|
||||
uses: actions/checkout@v3
|
||||
# See https://github.com/actions/checkout/commits
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
submodules: recursive
|
||||
path: geyser
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
# See https://github.com/gradle/wrapper-validation-action/commits
|
||||
uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
|
||||
|
||||
- name: Build Geyser
|
||||
uses: gradle/gradle-build-action@v2
|
||||
# See https://github.com/gradle/gradle-build-action/commits
|
||||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 from https://github.com/gradle/actions/commits
|
||||
with:
|
||||
arguments: build
|
||||
build-root-directory: geyser
|
||||
|
||||
- name: Archive artifacts (Geyser Fabric)
|
||||
uses: actions/upload-artifact@v3
|
||||
# See https://github.com/actions/upload-artifact/commits
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Fabric
|
||||
path: geyser/bootstrap/fabric/build/libs/Geyser-Fabric.jar
|
||||
path: geyser/bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser NeoForge)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser NeoForge
|
||||
path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Standalone)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Standalone
|
||||
path: geyser/bootstrap/standalone/build/libs/Geyser-Standalone.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Spigot)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Spigot
|
||||
path: geyser/bootstrap/spigot/build/libs/Geyser-Spigot.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser BungeeCord)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser BungeeCord
|
||||
path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Sponge)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Sponge
|
||||
path: geyser/bootstrap/sponge/build/libs/Geyser-Sponge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Velocity)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Velocity
|
||||
path: geyser/bootstrap/velocity/build/libs/Geyser-Velocity.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser ViaProxy)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser ViaProxy
|
||||
path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
|
||||
if-no-files-found: error
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -251,3 +251,4 @@ locales/
|
|||
/saved-refresh-tokens.json
|
||||
/custom_mappings/
|
||||
/languages/
|
||||
/custom-skulls.yml
|
|
@ -19,32 +19,28 @@ public class LongClassName {
|
|||
public int nameWithMultipleWords = 0;
|
||||
|
||||
/**
|
||||
* Javadoc comment to explain what a function does.
|
||||
*/
|
||||
* Javadoc comment to explain what a function does.
|
||||
*/
|
||||
@RandomAnnotation(stuff = true, moreStuff = "might exist")
|
||||
public void applyStuff() {
|
||||
Variable variable = new Variable();
|
||||
Variable otherVariable = new Variable();
|
||||
|
||||
if (condition) {
|
||||
// Do stuff.
|
||||
// Do stuff.
|
||||
} else if (anotherCondition) {
|
||||
// Do something else.
|
||||
// Do something else.
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case 0:
|
||||
stuff();
|
||||
break;
|
||||
case 1:
|
||||
differentStuff();
|
||||
break;
|
||||
case 0 -> stuff();
|
||||
case 1 -> differentStuff();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to comment your code where possible.
|
||||
Make sure to comment your code where possible. To mark nullable methods, use `@Nullable` (and subsequently, `@NonNull`) from the `org.checkerframework.checker.nullness.qual` package.
|
||||
|
||||
The nature of our software requires a lot of arrays and maps to be stored - where possible, use Fastutil's specialized maps. For example, if you're storing block state translations, use an `Int2IntMap`.
|
||||
|
||||
|
|
28
Jenkinsfile
vendored
28
Jenkinsfile
vendored
|
@ -1,28 +0,0 @@
|
|||
pipeline {
|
||||
agent any
|
||||
tools {
|
||||
gradle 'Gradle 7'
|
||||
jdk 'Java 17'
|
||||
}
|
||||
options {
|
||||
buildDiscarder(logRotator(artifactNumToKeepStr: '20'))
|
||||
}
|
||||
stages {
|
||||
stage ('Build') {
|
||||
steps {
|
||||
sh 'git submodule update --init --recursive'
|
||||
rtGradleRun(
|
||||
usesPlugin: true,
|
||||
tool: 'Gradle 7',
|
||||
buildFile: 'build.gradle.kts',
|
||||
tasks: 'clean build',
|
||||
)
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'bootstrap/**/build/libs/Geyser-*.jar', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
|
|||
|
||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
|
||||
|
||||
### Currently supporting Minecraft Bedrock 1.19.40 - 1.19.81 and Minecraft Java 1.19.4.
|
||||
### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.72 and Minecraft Java 1.20.4
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
|
||||
|
|
|
@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion;
|
|||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
public class BlockEntityProcessor extends ClassProcessor {
|
||||
public BlockEntityProcessor() {
|
||||
super("org.geysermc.geyser.translator.level.block.entity.BlockEntity");
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser.processor;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
|
@ -159,7 +161,7 @@ public class ClassProcessor extends AbstractProcessor {
|
|||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Completed processing for " + this.annotationClassName);
|
||||
}
|
||||
|
||||
private BufferedReader createReader() throws IOException {
|
||||
private @Nullable BufferedReader createReader() throws IOException {
|
||||
if (this.outputPath != null) {
|
||||
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Reading existing " + this.annotationClassName + " list from " + this.outputPath);
|
||||
return Files.newBufferedReader(this.outputPath);
|
||||
|
|
|
@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion;
|
|||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
public class CollisionRemapperProcessor extends ClassProcessor {
|
||||
public CollisionRemapperProcessor() {
|
||||
super("org.geysermc.geyser.translator.collision.CollisionRemapper");
|
||||
|
|
|
@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion;
|
|||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
public class PacketTranslatorProcessor extends ClassProcessor {
|
||||
public PacketTranslatorProcessor() {
|
||||
super("org.geysermc.geyser.translator.protocol.Translator");
|
||||
|
|
|
@ -30,7 +30,7 @@ import javax.annotation.processing.SupportedSourceVersion;
|
|||
import javax.lang.model.SourceVersion;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_16)
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
public class SoundHandlerProcessor extends ClassProcessor {
|
||||
public SoundHandlerProcessor() {
|
||||
super("org.geysermc.geyser.translator.sound.SoundTranslator");
|
||||
|
|
|
@ -4,4 +4,5 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
api(libs.base.api)
|
||||
api(libs.math)
|
||||
}
|
|
@ -29,13 +29,17 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.geyser.api.command.CommandSource;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.event.EventBus;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.extension.ExtensionManager;
|
||||
import org.geysermc.geyser.api.network.BedrockListener;
|
||||
import org.geysermc.geyser.api.network.RemoteServer;
|
||||
import org.geysermc.geyser.api.util.MinecraftVersion;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -75,6 +79,7 @@ public interface GeyserApi extends GeyserApiBase {
|
|||
* @param apiClass the builder class
|
||||
* @param <R> the implementation type
|
||||
* @param <T> the API type
|
||||
* @throws IllegalArgumentException if there is no provider for the specified API class
|
||||
* @return the builder instance
|
||||
*/
|
||||
@NonNull
|
||||
|
@ -107,6 +112,54 @@ public interface GeyserApi extends GeyserApiBase {
|
|||
@NonNull
|
||||
BedrockListener bedrockListener();
|
||||
|
||||
/**
|
||||
* Gets the {@link Path} to the Geyser config directory.
|
||||
*
|
||||
* @return the path to the Geyser config directory
|
||||
*/
|
||||
@NonNull
|
||||
Path configDirectory();
|
||||
|
||||
/**
|
||||
* Gets the {@link Path} to the Geyser packs directory.
|
||||
*
|
||||
* @return the path to the Geyser packs directory
|
||||
*/
|
||||
@NonNull
|
||||
Path packDirectory();
|
||||
|
||||
/**
|
||||
* Gets {@link PlatformType} the extension is running on
|
||||
*
|
||||
* @return type of platform
|
||||
*/
|
||||
@NonNull
|
||||
PlatformType platformType();
|
||||
|
||||
/**
|
||||
* Gets the version of Java Minecraft that is supported.
|
||||
*
|
||||
* @return the supported version of Java Minecraft
|
||||
*/
|
||||
@NonNull
|
||||
MinecraftVersion supportedJavaVersion();
|
||||
|
||||
/**
|
||||
* Gets a list of Bedrock Minecraft versions that are supported.
|
||||
*
|
||||
* @return the list of supported Bedrock Minecraft versions
|
||||
*/
|
||||
@NonNull
|
||||
List<MinecraftVersion> supportedBedrockVersions();
|
||||
|
||||
/**
|
||||
* Gets the {@link CommandSource} for the console.
|
||||
*
|
||||
* @return the console command source
|
||||
*/
|
||||
@NonNull
|
||||
CommandSource consoleCommandSource();
|
||||
|
||||
/**
|
||||
* Gets the current {@link GeyserApiBase} instance.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This interface holds all the methods that relate to a client's camera.
|
||||
* Can be accessed through {@link GeyserConnection#camera()}.
|
||||
*/
|
||||
public interface CameraData {
|
||||
|
||||
/**
|
||||
* Sends a camera fade instruction to the client.
|
||||
* If an existing camera fade is already in progress, the current fade will be prolonged.
|
||||
* Can be built using {@link CameraFade.Builder}.
|
||||
* To stop a fade early, use {@link #clearCameraInstructions()}.
|
||||
*
|
||||
* @param fade the camera fade instruction to send
|
||||
*/
|
||||
void sendCameraFade(@NonNull CameraFade fade);
|
||||
|
||||
/**
|
||||
* Sends a camera position instruction to the client.
|
||||
* If an existing camera movement is already in progress,
|
||||
* the final camera position will be the one of the latest instruction, and
|
||||
* the (optional) camera fade will be added on top of the existing fade.
|
||||
* Can be built using {@link CameraPosition.Builder}.
|
||||
* To stop reset the camera position/stop ongoing instructions, use {@link #clearCameraInstructions()}.
|
||||
*
|
||||
* @param position the camera position instruction to send
|
||||
*/
|
||||
void sendCameraPosition(@NonNull CameraPosition position);
|
||||
|
||||
/**
|
||||
* Stops all sent camera instructions (fades, movements, and perspective locks).
|
||||
* This will not stop any camera shakes/input locks/fog effects, use the respective methods for those.
|
||||
*/
|
||||
void clearCameraInstructions();
|
||||
|
||||
/**
|
||||
* Forces a {@link CameraPerspective} on the client. This will prevent the client
|
||||
* from changing their camera perspective until it is unlocked via {@link #clearCameraInstructions()}.
|
||||
* <p>
|
||||
* Note: You cannot force a client into a free camera perspective with this method.
|
||||
* To do that, send a {@link CameraPosition} via {@link #sendCameraPosition(CameraPosition)} - it requires a set position
|
||||
* instead of being relative to the player.
|
||||
*
|
||||
* @param perspective the {@link CameraPerspective} to force
|
||||
*/
|
||||
void forceCameraPerspective(@NonNull CameraPerspective perspective);
|
||||
|
||||
/**
|
||||
* Gets the client's current {@link CameraPerspective}, if one is currently forced.
|
||||
* This will return {@code null} if the client is not currently forced into a perspective.
|
||||
* If a perspective is forced, the client will not be able to change their camera perspective until it is unlocked.
|
||||
*
|
||||
* @return the forced perspective, or {@code null} if none is forced
|
||||
*/
|
||||
@Nullable CameraPerspective forcedCameraPerspective();
|
||||
|
||||
/**
|
||||
* Shakes the client's camera.
|
||||
* <p>
|
||||
* If the camera is already shaking with the same {@link CameraShake} type, then the additional intensity
|
||||
* will be layered on top of the existing intensity, with their own distinct durations.<br>
|
||||
* If the existing shake type is different and the new intensity/duration are not positive, the existing shake only
|
||||
* switches to the new type. Otherwise, the existing shake is completely overridden.
|
||||
*
|
||||
* @param intensity the intensity of the shake. The client has a maximum total intensity of 4.
|
||||
* @param duration the time in seconds that the shake will occur for
|
||||
* @param type the type of shake
|
||||
*/
|
||||
void shakeCamera(float intensity, float duration, @NonNull CameraShake type);
|
||||
|
||||
/**
|
||||
* Stops all camera shakes of any type.
|
||||
*/
|
||||
void stopCameraShake();
|
||||
|
||||
/**
|
||||
* Adds the given fog IDs to the fog cache, then sends all fog IDs in the cache to the client.
|
||||
* <p>
|
||||
* Fog IDs can be found <a href="https://wiki.bedrock.dev/documentation/fog-ids.html">here</a>
|
||||
*
|
||||
* @param fogNameSpaces the fog IDs to add. If empty, the existing cached IDs will still be sent.
|
||||
*/
|
||||
void sendFog(String... fogNameSpaces);
|
||||
|
||||
/**
|
||||
* Removes the given fog IDs from the fog cache, then sends all fog IDs in the cache to the client.
|
||||
*
|
||||
* @param fogNameSpaces the fog IDs to remove. If empty, all fog IDs will be removed.
|
||||
*/
|
||||
void removeFog(String... fogNameSpaces);
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of all fog affects currently applied to this client.
|
||||
*/
|
||||
@NonNull
|
||||
Set<String> fogEffects();
|
||||
|
||||
/**
|
||||
* (Un)locks the client's camera, so that they cannot look around.
|
||||
* To ensure the camera is only unlocked when all locks are released, you must supply
|
||||
* a UUID when using method, and use the same UUID to unlock the camera.
|
||||
*
|
||||
* @param lock whether to lock the camera
|
||||
* @param owner the owner of the lock, represented with a UUID
|
||||
* @return if the camera is locked after this method call
|
||||
*/
|
||||
boolean lockCamera(boolean lock, @NonNull UUID owner);
|
||||
|
||||
/**
|
||||
* Returns whether the client's camera is locked.
|
||||
*
|
||||
* @return whether the camera is currently locked
|
||||
*/
|
||||
boolean isCameraLocked();
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
/**
|
||||
* These are all the easing types that can be used when sending a {@link CameraPosition} instruction.
|
||||
* When using these, the client won't teleport to the new camera position, but instead transition to it.
|
||||
* <p>
|
||||
* See <a href="https://easings.net/">https://easings.net/</a> for more information.
|
||||
*/
|
||||
public enum CameraEaseType {
|
||||
LINEAR("linear"),
|
||||
SPRING("spring"),
|
||||
EASE_IN_SINE("in_sine"),
|
||||
EASE_OUT_SINE("out_sine"),
|
||||
EASE_IN_OUT_SINE("in_out_sine"),
|
||||
EASE_IN_QUAD("in_quad"),
|
||||
EASE_OUT_QUAD("out_quad"),
|
||||
EASE_IN_OUT_QUAD("in_out_quad"),
|
||||
EASE_IN_CUBIC("in_cubic"),
|
||||
EASE_OUT_CUBIC("out_cubic"),
|
||||
EASE_IN_OUT_CUBIC("in_out_cubic"),
|
||||
EASE_IN_QUART("in_quart"),
|
||||
EASE_OUT_QUART("out_quart"),
|
||||
EASE_IN_OUT_QUART("in_out_quart"),
|
||||
EASE_IN_QUINT("in_quint"),
|
||||
EASE_OUT_QUINT("out_quint"),
|
||||
EASE_IN_OUT_QUINT("in_out_quint"),
|
||||
EASE_IN_EXPO("in_expo"),
|
||||
EASE_OUT_EXPO("out_expo"),
|
||||
EASE_IN_OUT_EXPO("in_out_expo"),
|
||||
EASE_IN_CIRC("in_circ"),
|
||||
EASE_OUT_CIRC("out_circ"),
|
||||
EASE_IN_OUT_CIRC("in_out_circ"),
|
||||
EASE_IN_BACK("in_back"),
|
||||
EASE_OUT_BACK("out_back"),
|
||||
EASE_IN_OUT_BACK("in_out_back"),
|
||||
EASE_IN_ELASTIC("in_elastic"),
|
||||
EASE_OUT_ELASTIC("out_elastic"),
|
||||
EASE_IN_OUT_ELASTIC("in_out_elastic"),
|
||||
EASE_IN_BOUNCE("in_bounce"),
|
||||
EASE_OUT_BOUNCE("out_bounce"),
|
||||
EASE_IN_OUT_BOUNCE("in_out_bounce");
|
||||
|
||||
private final String id;
|
||||
|
||||
CameraEaseType(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* Represents a coloured fade overlay on the camera.
|
||||
* <p>
|
||||
* Can be sent with {@link CameraData#sendCameraFade(CameraFade)}, or with a {@link CameraPosition} instruction.
|
||||
*/
|
||||
public interface CameraFade {
|
||||
|
||||
/**
|
||||
* Gets the color overlay of the camera.
|
||||
* Bedrock uses an RGB color system.
|
||||
*
|
||||
* @return the color of the fade
|
||||
*/
|
||||
@NonNull Color color();
|
||||
|
||||
/**
|
||||
* Gets the seconds it takes to fade in.
|
||||
* All fade times combined must take at least 0.5 seconds, and at most 30 seconds.
|
||||
*
|
||||
* @return the seconds it takes to fade in
|
||||
*/
|
||||
float fadeInSeconds();
|
||||
|
||||
/**
|
||||
* Gets the seconds the overlay is held.
|
||||
* All fade times combined must take at least 0.5 seconds, and at most 30 seconds.
|
||||
*
|
||||
* @return the seconds the overlay is held
|
||||
*/
|
||||
float fadeHoldSeconds();
|
||||
|
||||
/**
|
||||
* Gets the seconds it takes to fade out.
|
||||
* All fade times combined must take at least 0.5 seconds, and at most 30 seconds.
|
||||
*
|
||||
* @return the seconds it takes to fade out
|
||||
*/
|
||||
float fadeOutSeconds();
|
||||
|
||||
/**
|
||||
* Creates a Builder for CameraFade
|
||||
*
|
||||
* @return a CameraFade Builder
|
||||
*/
|
||||
static CameraFade.Builder builder() {
|
||||
return GeyserApi.api().provider(CameraFade.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder color(@NonNull Color color);
|
||||
|
||||
Builder fadeInSeconds(@IntRange(from = 0, to = 10) float fadeInSeconds);
|
||||
|
||||
Builder fadeHoldSeconds(@IntRange(from = 0, to = 10) float fadeHoldSeconds);
|
||||
|
||||
Builder fadeOutSeconds(@IntRange(from = 0, to = 10) float fadeOutSeconds);
|
||||
|
||||
CameraFade build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
/**
|
||||
* Represents a camera perspective that a player's camera can take.
|
||||
* All perspectives except for {@link #FREE} are locked to the player's head,
|
||||
* and are therefore relative to the player's position and rotation.
|
||||
*/
|
||||
public enum CameraPerspective {
|
||||
FIRST_PERSON("minecraft:first_person"),
|
||||
FREE("minecraft:free"),
|
||||
THIRD_PERSON("minecraft:third_person"),
|
||||
THIRD_PERSON_FRONT("minecraft:third_person_front");
|
||||
|
||||
private final String id;
|
||||
|
||||
CameraPerspective(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
/**
|
||||
* This interface represents a camera position instruction. Can be built with the {@link #builder()}.
|
||||
* <p>
|
||||
* Any camera position instruction pins the client camera to a specific position and rotation.
|
||||
* You can set {@link CameraEaseType} to ensure a smooth transition that will last {@link #easeSeconds()} seconds.
|
||||
* A {@link CameraFade} can also be sent, which will transition the player to a coloured transition during the transition.
|
||||
* <p>
|
||||
* Use {@link CameraData#sendCameraPosition(CameraPosition)} to send such an instruction to any connection.
|
||||
*/
|
||||
public interface CameraPosition {
|
||||
|
||||
/**
|
||||
* Gets the camera's position.
|
||||
*
|
||||
* @return camera position vector
|
||||
*/
|
||||
@NonNull Vector3f position();
|
||||
|
||||
/**
|
||||
* Gets the {@link CameraEaseType} of the camera.
|
||||
* If not set, there is no easing.
|
||||
*
|
||||
* @return camera ease type
|
||||
*/
|
||||
@Nullable CameraEaseType easeType();
|
||||
|
||||
/**
|
||||
* Gets the {@link CameraFade} to be sent along the camera position instruction.
|
||||
* If set, they will run at once.
|
||||
*
|
||||
* @return camera fade, or null if not present
|
||||
*/
|
||||
@Nullable CameraFade cameraFade();
|
||||
|
||||
/**
|
||||
* Gets the easing duration of the camera, in seconds.
|
||||
* Is only used if a {@link CameraEaseType} is set.
|
||||
*
|
||||
* @return camera easing duration in seconds
|
||||
*/
|
||||
float easeSeconds();
|
||||
|
||||
/**
|
||||
* Gets the x-axis rotation of the camera.
|
||||
* To prevent the camera from being upside down, Bedrock limits the range to -90 to 90.
|
||||
* Will be overridden if {@link #facingPosition()} is set.
|
||||
*
|
||||
* @return camera x-axis rotation
|
||||
*/
|
||||
@IntRange(from = -90, to = 90) int rotationX();
|
||||
|
||||
/**
|
||||
* Gets the y-axis rotation of the camera.
|
||||
* Will be overridden if {@link #facingPosition()} is set.
|
||||
*
|
||||
* @return camera y-axis rotation
|
||||
*/
|
||||
int rotationY();
|
||||
|
||||
/**
|
||||
* Gets the position that the camera is facing.
|
||||
* Can be used instead of manually setting rotation values.
|
||||
* <p>
|
||||
* If set, the rotation values set via {@link #rotationX()} and {@link #rotationY()} will be ignored.
|
||||
*
|
||||
* @return Camera's facing position
|
||||
*/
|
||||
@Nullable Vector3f facingPosition();
|
||||
|
||||
/**
|
||||
* Controls whether player effects, such as night vision or blindness, should be rendered on the camera.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return whether player effects should be rendered
|
||||
*/
|
||||
boolean renderPlayerEffects();
|
||||
|
||||
/**
|
||||
* Controls whether the player position should be used for directional audio.
|
||||
* If false, the camera position will be used instead.
|
||||
*
|
||||
* @return whether the players position should be used for directional audio
|
||||
*/
|
||||
boolean playerPositionForAudio();
|
||||
|
||||
/**
|
||||
* Creates a Builder for CameraPosition
|
||||
*
|
||||
* @return a CameraPosition Builder
|
||||
*/
|
||||
static CameraPosition.Builder builder() {
|
||||
return GeyserApi.api().provider(CameraPosition.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
|
||||
Builder cameraFade(@Nullable CameraFade cameraFade);
|
||||
|
||||
Builder renderPlayerEffects(boolean renderPlayerEffects);
|
||||
|
||||
Builder playerPositionForAudio(boolean playerPositionForAudio);
|
||||
|
||||
Builder easeType(@Nullable CameraEaseType easeType);
|
||||
|
||||
Builder easeSeconds(float easeSeconds);
|
||||
|
||||
Builder position(@NonNull Vector3f position);
|
||||
|
||||
Builder rotationX(@IntRange(from = -90, to = 90) int rotationX);
|
||||
|
||||
Builder rotationY(int rotationY);
|
||||
|
||||
Builder facingPosition(@Nullable Vector3f facingPosition);
|
||||
|
||||
CameraPosition build();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,21 +23,12 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.common;
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PlatformType {
|
||||
ANDROID("Android"),
|
||||
BUNGEECORD("BungeeCord"),
|
||||
FABRIC("Fabric"),
|
||||
SPIGOT("Spigot"),
|
||||
SPONGE("Sponge"),
|
||||
STANDALONE("Standalone"),
|
||||
VELOCITY("Velocity");
|
||||
|
||||
private final String platformName;
|
||||
/**
|
||||
* Represents a camera shake instruction. Can be sent in {@link CameraData#shakeCamera(float, float, CameraShake)}
|
||||
*/
|
||||
public enum CameraShake {
|
||||
POSITIONAL,
|
||||
ROTATIONAL
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
|
||||
import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty;
|
||||
import org.geysermc.geyser.api.util.CreativeCategory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class is used to store data for a custom block.
|
||||
*/
|
||||
public interface CustomBlockData {
|
||||
/**
|
||||
* Gets the name of the custom block
|
||||
*
|
||||
* @return The name of the custom block.
|
||||
*/
|
||||
@NonNull String name();
|
||||
|
||||
/**
|
||||
* Gets the identifier of the custom block
|
||||
*
|
||||
* @return The identifier of the custom block.
|
||||
*/
|
||||
@NonNull String identifier();
|
||||
|
||||
/**
|
||||
* Gets if the custom block is included in the creative inventory
|
||||
*
|
||||
* @return If the custom block is included in the creative inventory.
|
||||
*/
|
||||
boolean includedInCreativeInventory();
|
||||
|
||||
/**
|
||||
* Gets the block's creative category, or tab id.
|
||||
*
|
||||
* @return the block's creative category
|
||||
*/
|
||||
@Nullable CreativeCategory creativeCategory();
|
||||
|
||||
/**
|
||||
* Gets the block's creative group.
|
||||
*
|
||||
* @return the block's creative group
|
||||
*/
|
||||
@Nullable String creativeGroup();
|
||||
|
||||
/**
|
||||
* Gets the components of the custom block
|
||||
*
|
||||
* @return The components of the custom block.
|
||||
*/
|
||||
@Nullable CustomBlockComponents components();
|
||||
|
||||
/**
|
||||
* Gets the custom block's map of block property names to CustomBlockProperty
|
||||
* objects
|
||||
*
|
||||
* @return The custom block's map of block property names to CustomBlockProperty objects.
|
||||
*/
|
||||
@NonNull Map<String, CustomBlockProperty<?>> properties();
|
||||
|
||||
/**
|
||||
* Gets the list of the custom block's permutations
|
||||
*
|
||||
* @return The permutations of the custom block.
|
||||
*/
|
||||
@NonNull List<CustomBlockPermutation> permutations();
|
||||
|
||||
/**
|
||||
* Gets the custom block's default block state
|
||||
*
|
||||
* @return The default block state of the custom block.
|
||||
*/
|
||||
@NonNull CustomBlockState defaultBlockState();
|
||||
|
||||
/**
|
||||
* Gets a builder for a custom block state
|
||||
*
|
||||
* @return The builder for a custom block state.
|
||||
*/
|
||||
CustomBlockState.@NonNull Builder blockStateBuilder();
|
||||
|
||||
/**
|
||||
* Create a Builder for CustomBlockData
|
||||
*
|
||||
* @return A CustomBlockData Builder
|
||||
*/
|
||||
static CustomBlockData.Builder builder() {
|
||||
return GeyserApi.api().provider(CustomBlockData.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
Builder name(@NonNull String name);
|
||||
|
||||
Builder includedInCreativeInventory(boolean includedInCreativeInventory);
|
||||
|
||||
Builder creativeCategory(@Nullable CreativeCategory creativeCategory);
|
||||
|
||||
Builder creativeGroup(@Nullable String creativeGroup);
|
||||
|
||||
Builder components(@NonNull CustomBlockComponents components);
|
||||
|
||||
Builder booleanProperty(@NonNull String propertyName);
|
||||
|
||||
Builder intProperty(@NonNull String propertyName, List<Integer> values);
|
||||
|
||||
Builder stringProperty(@NonNull String propertyName, List<String> values);
|
||||
|
||||
Builder permutations(@NonNull List<CustomBlockPermutation> permutations);
|
||||
|
||||
CustomBlockData build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
|
||||
|
||||
/**
|
||||
* This class is used to store a custom block permutations, which contain custom
|
||||
* block components mapped to a Molang query that should return true or false
|
||||
*
|
||||
* @param components The components of the block
|
||||
* @param condition The Molang query that should return true or false
|
||||
*/
|
||||
public record CustomBlockPermutation(@NonNull CustomBlockComponents components, @NonNull String condition) {
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class is used to store a custom block state, which contains CustomBlockData
|
||||
* tied to defined properties and values
|
||||
*/
|
||||
public interface CustomBlockState {
|
||||
/**
|
||||
* Gets the custom block data associated with the state
|
||||
*
|
||||
* @return The custom block data for the state.
|
||||
*/
|
||||
@NonNull CustomBlockData block();
|
||||
|
||||
/**
|
||||
* Gets the name of the state
|
||||
*
|
||||
* @return The name of the state.
|
||||
*/
|
||||
@NonNull String name();
|
||||
|
||||
/**
|
||||
* Gets the given property for the state
|
||||
*
|
||||
* @param propertyName the property name
|
||||
* @return the boolean, int, or string property.
|
||||
*/
|
||||
@NonNull <T> T property(@NonNull String propertyName);
|
||||
|
||||
/**
|
||||
* Gets a map of the properties for the state
|
||||
*
|
||||
* @return The properties for the state.
|
||||
*/
|
||||
@NonNull Map<String, Object> properties();
|
||||
|
||||
interface Builder {
|
||||
Builder booleanProperty(@NonNull String propertyName, boolean value);
|
||||
|
||||
Builder intProperty(@NonNull String propertyName, int value);
|
||||
|
||||
Builder stringProperty(@NonNull String propertyName, @NonNull String value);
|
||||
|
||||
CustomBlockState build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
|
||||
import org.geysermc.geyser.api.util.CreativeCategory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a completely custom block that is not based on an existing vanilla Minecraft block.
|
||||
*/
|
||||
public interface NonVanillaCustomBlockData extends CustomBlockData {
|
||||
/**
|
||||
* Gets the namespace of the custom block
|
||||
*
|
||||
* @return The namespace of the custom block.
|
||||
*/
|
||||
@NonNull String namespace();
|
||||
|
||||
|
||||
/**
|
||||
* Create a Builder for NonVanillaCustomBlockData
|
||||
*
|
||||
* @return A NonVanillaCustomBlockData Builder
|
||||
*/
|
||||
static NonVanillaCustomBlockData.Builder builder() {
|
||||
return GeyserApi.api().provider(NonVanillaCustomBlockData.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder extends CustomBlockData.Builder {
|
||||
|
||||
Builder namespace(@NonNull String namespace);
|
||||
|
||||
@Override
|
||||
Builder name(@NonNull String name);
|
||||
|
||||
@Override
|
||||
Builder includedInCreativeInventory(boolean includedInCreativeInventory);
|
||||
|
||||
@Override
|
||||
Builder creativeCategory(@Nullable CreativeCategory creativeCategory);
|
||||
|
||||
@Override
|
||||
Builder creativeGroup(@Nullable String creativeGroup);
|
||||
|
||||
@Override
|
||||
Builder components(@NonNull CustomBlockComponents components);
|
||||
|
||||
@Override
|
||||
Builder booleanProperty(@NonNull String propertyName);
|
||||
|
||||
@Override
|
||||
Builder intProperty(@NonNull String propertyName, List<Integer> values);
|
||||
|
||||
@Override
|
||||
Builder stringProperty(@NonNull String propertyName, List<String> values);
|
||||
|
||||
@Override
|
||||
Builder permutations(@NonNull List<CustomBlockPermutation> permutations);
|
||||
|
||||
@Override
|
||||
NonVanillaCustomBlockData build();
|
||||
}
|
||||
}
|
|
@ -23,42 +23,47 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.translator.inventory.item;
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public abstract class NbtItemStackTranslator {
|
||||
/**
|
||||
* This class is used to store a box component for the selection and
|
||||
* collision boxes of a custom block.
|
||||
*
|
||||
* @param originX The origin X of the box
|
||||
* @param originY The origin Y of the box
|
||||
* @param originZ The origin Z of the box
|
||||
* @param sizeX The size X of the box
|
||||
* @param sizeY The size Y of the box
|
||||
* @param sizeZ The size Z of the box
|
||||
*/
|
||||
public record BoxComponent(float originX, float originY, float originZ, float sizeX, float sizeY, float sizeZ) {
|
||||
private static final BoxComponent FULL_BOX = new BoxComponent(-8, 0, -8, 16, 16, 16);
|
||||
private static final BoxComponent EMPTY_BOX = new BoxComponent(0, 0, 0, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* Translate the item NBT to Bedrock
|
||||
* @param session the client's current session
|
||||
* @param itemTag the item's CompoundTag (cloned from Geyser's cached copy)
|
||||
* @param mapping Geyser's item mapping
|
||||
*/
|
||||
public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemMapping mapping) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the item NBT to Java.
|
||||
* @param itemTag the item's CompoundTag
|
||||
* @param mapping Geyser's item mapping
|
||||
*/
|
||||
public void translateToJava(CompoundTag itemTag, ItemMapping mapping) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this nbt translator takes in this item.
|
||||
* Gets a full box component
|
||||
*
|
||||
* @param item Geyser's item mapping
|
||||
* @return if the item should be processed under this class
|
||||
* @return A full box component
|
||||
*/
|
||||
public boolean acceptItem(Item item) {
|
||||
return true;
|
||||
} // TODO
|
||||
public static BoxComponent fullBox() {
|
||||
return FULL_BOX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an empty box component
|
||||
*
|
||||
* @return An empty box component
|
||||
*/
|
||||
public static BoxComponent emptyBox() {
|
||||
return EMPTY_BOX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the box component is empty
|
||||
*
|
||||
* @return If the box component is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return sizeX == 0 && sizeY == 0 && sizeZ == 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class is used to store components for a custom block or custom block permutation.
|
||||
*/
|
||||
public interface CustomBlockComponents {
|
||||
|
||||
/**
|
||||
* Gets the selection box component
|
||||
* Equivalent to "minecraft:selection_box"
|
||||
*
|
||||
* @return The selection box.
|
||||
*/
|
||||
@Nullable BoxComponent selectionBox();
|
||||
|
||||
/**
|
||||
* Gets the collision box component
|
||||
* Equivalent to "minecraft:collision_box"
|
||||
* @return The collision box.
|
||||
*/
|
||||
@Nullable BoxComponent collisionBox();
|
||||
|
||||
/**
|
||||
* Gets the display name component
|
||||
* Equivalent to "minecraft:display_name"
|
||||
*
|
||||
* @return The display name.
|
||||
*/
|
||||
@Nullable String displayName();
|
||||
|
||||
/**
|
||||
* Gets the geometry component
|
||||
* Equivalent to "minecraft:geometry"
|
||||
*
|
||||
* @return The geometry.
|
||||
*/
|
||||
@Nullable GeometryComponent geometry();
|
||||
|
||||
/**
|
||||
* Gets the material instances component
|
||||
* Equivalent to "minecraft:material_instances"
|
||||
*
|
||||
* @return The material instances.
|
||||
*/
|
||||
@NonNull Map<String, MaterialInstance> materialInstances();
|
||||
|
||||
/**
|
||||
* Gets the placement filter component
|
||||
* Equivalent to "minecraft:placement_filter"
|
||||
*
|
||||
* @return The placement filter.
|
||||
*/
|
||||
@Nullable List<PlacementConditions> placementFilter();
|
||||
|
||||
/**
|
||||
* Gets the destructible by mining component
|
||||
* Equivalent to "minecraft:destructible_by_mining"
|
||||
*
|
||||
* @return The destructible by mining value.
|
||||
*/
|
||||
@Nullable Float destructibleByMining();
|
||||
|
||||
/**
|
||||
* Gets the friction component
|
||||
* Equivalent to "minecraft:friction"
|
||||
*
|
||||
* @return The friction value.
|
||||
*/
|
||||
@Nullable Float friction();
|
||||
|
||||
/**
|
||||
* Gets the light emission component
|
||||
* Equivalent to "minecraft:light_emission"
|
||||
*
|
||||
* @return The light emission value.
|
||||
*/
|
||||
@Nullable Integer lightEmission();
|
||||
|
||||
/**
|
||||
* Gets the light dampening component
|
||||
* Equivalent to "minecraft:light_dampening"
|
||||
*
|
||||
* @return The light dampening value.
|
||||
*/
|
||||
@Nullable Integer lightDampening();
|
||||
|
||||
/**
|
||||
* Gets the transformation component
|
||||
* Equivalent to "minecraft:transformation"
|
||||
*
|
||||
* @return The transformation.
|
||||
*/
|
||||
@Nullable TransformationComponent transformation();
|
||||
|
||||
/**
|
||||
* Gets the unit cube component
|
||||
* Equivalent to "minecraft:unit_cube"
|
||||
*
|
||||
* @deprecated Use {@link #geometry()} and compare with `minecraft:geometry.full_block` instead.
|
||||
*
|
||||
* @return The rotation.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean unitCube();
|
||||
|
||||
/**
|
||||
* Gets if the block should place only air
|
||||
* Equivalent to setting a dummy event to run on "minecraft:on_player_placing"
|
||||
*
|
||||
* @return If the block should place only air.
|
||||
*/
|
||||
boolean placeAir();
|
||||
|
||||
/**
|
||||
* Gets the set of tags
|
||||
* Equivalent to "tag:some_tag"
|
||||
*
|
||||
* @return The set of tags.
|
||||
*/
|
||||
@NonNull Set<String> tags();
|
||||
|
||||
/**
|
||||
* Create a Builder for CustomBlockComponents
|
||||
*
|
||||
* @return A CustomBlockComponents Builder
|
||||
*/
|
||||
static CustomBlockComponents.Builder builder() {
|
||||
return GeyserApi.api().provider(CustomBlockComponents.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
Builder selectionBox(BoxComponent selectionBox);
|
||||
|
||||
Builder collisionBox(BoxComponent collisionBox);
|
||||
|
||||
Builder displayName(String displayName);
|
||||
|
||||
Builder geometry(GeometryComponent geometry);
|
||||
|
||||
Builder materialInstance(@NonNull String name, @NonNull MaterialInstance materialInstance);
|
||||
|
||||
Builder placementFilter(List<PlacementConditions> placementConditions);
|
||||
|
||||
Builder destructibleByMining(Float destructibleByMining);
|
||||
|
||||
Builder friction(Float friction);
|
||||
|
||||
Builder lightEmission(Integer lightEmission);
|
||||
|
||||
Builder lightDampening(Integer lightDampening);
|
||||
|
||||
Builder transformation(TransformationComponent transformation);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #geometry(GeometryComponent)} with `minecraft:geometry.full_block` instead.
|
||||
*/
|
||||
@Deprecated
|
||||
Builder unitCube(boolean unitCube);
|
||||
|
||||
Builder placeAir(boolean placeAir);
|
||||
|
||||
Builder tags(@Nullable Set<String> tags);
|
||||
|
||||
CustomBlockComponents build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class is used to store data for a geometry component.
|
||||
*/
|
||||
public interface GeometryComponent {
|
||||
|
||||
/**
|
||||
* Gets the identifier of the geometry
|
||||
*
|
||||
* @return The identifier of the geometry.
|
||||
*/
|
||||
@NonNull String identifier();
|
||||
|
||||
/**
|
||||
* Gets the bone visibility of the geometry
|
||||
*
|
||||
* @return The bone visibility of the geometry.
|
||||
*/
|
||||
@Nullable Map<String, String> boneVisibility();
|
||||
|
||||
/**
|
||||
* Creates a builder for GeometryComponent
|
||||
*
|
||||
* @return a builder for GeometryComponent.
|
||||
*/
|
||||
static GeometryComponent.Builder builder() {
|
||||
return GeyserApi.api().provider(GeometryComponent.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
Builder identifier(@NonNull String identifier);
|
||||
|
||||
Builder boneVisibility(@Nullable Map<String, String> boneVisibility);
|
||||
|
||||
GeometryComponent build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
/**
|
||||
* This class is used to store data for a material instance.
|
||||
*/
|
||||
public interface MaterialInstance {
|
||||
/**
|
||||
* Gets the texture of the block
|
||||
*
|
||||
* @return The texture of the block.
|
||||
*/
|
||||
@Nullable String texture();
|
||||
|
||||
/**
|
||||
* Gets the render method of the block
|
||||
*
|
||||
* @return The render method of the block.
|
||||
*/
|
||||
@Nullable String renderMethod();
|
||||
|
||||
/**
|
||||
* Gets if the block should be dimmed on certain faces
|
||||
*
|
||||
* @return If the block should be dimmed on certain faces.
|
||||
*/
|
||||
boolean faceDimming();
|
||||
|
||||
/**
|
||||
* Gets if the block should have ambient occlusion
|
||||
*
|
||||
* @return If the block should have ambient occlusion.
|
||||
*/
|
||||
boolean ambientOcclusion();
|
||||
|
||||
/**
|
||||
* Creates a builder for MaterialInstance.
|
||||
*
|
||||
* @return a builder for MaterialInstance
|
||||
*/
|
||||
static MaterialInstance.Builder builder() {
|
||||
return GeyserApi.api().provider(MaterialInstance.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
Builder texture(@Nullable String texture);
|
||||
|
||||
Builder renderMethod(@Nullable String renderMethod);
|
||||
|
||||
Builder faceDimming(boolean faceDimming);
|
||||
|
||||
Builder ambientOcclusion(boolean ambientOcclusion);
|
||||
|
||||
MaterialInstance build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class is used to store conditions for a placement filter for a custom block.
|
||||
*
|
||||
* @param allowedFaces The faces that the block can be placed on
|
||||
* @param blockFilters The block filters that control what blocks the block can be placed on
|
||||
*/
|
||||
public record PlacementConditions(@NonNull Set<Face> allowedFaces, @NonNull LinkedHashMap<String, BlockFilterType> blockFilters) {
|
||||
public enum Face {
|
||||
DOWN,
|
||||
UP,
|
||||
NORTH,
|
||||
SOUTH,
|
||||
WEST,
|
||||
EAST
|
||||
}
|
||||
|
||||
public enum BlockFilterType {
|
||||
BLOCK,
|
||||
TAG
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.component;
|
||||
|
||||
/**
|
||||
* This class is used to store the transformation component of a block
|
||||
*
|
||||
* @param rx The rotation on the x axis
|
||||
* @param ry The rotation on the y axis
|
||||
* @param rz The rotation on the z axis
|
||||
* @param sx The scale on the x axis
|
||||
* @param sy The scale on the y axis
|
||||
* @param sz The scale on the z axis
|
||||
* @param tx The translation on the x axis
|
||||
* @param ty The translation on the y axis
|
||||
* @param tz The translation on the z axis
|
||||
*/
|
||||
public record TransformationComponent(int rx, int ry, int rz, float sx, float sy, float sz, float tx, float ty, float tz) {
|
||||
|
||||
/**
|
||||
* Constructs a new TransformationComponent with the rotation values and assumes default scale and translation
|
||||
*
|
||||
* @param rx The rotation on the x axis
|
||||
* @param ry The rotation on the y axis
|
||||
* @param rz The rotation on the z axis
|
||||
*/
|
||||
public TransformationComponent(int rx, int ry, int rz) {
|
||||
this(rx, ry, rz, 1, 1, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new TransformationComponent with the rotation and scale values and assumes default translation
|
||||
*
|
||||
* @param rx The rotation on the x axis
|
||||
* @param ry The rotation on the y axis
|
||||
* @param rz The rotation on the z axis
|
||||
* @param sx The scale on the x axis
|
||||
* @param sy The scale on the y axis
|
||||
* @param sz The scale on the z axis
|
||||
*/
|
||||
public TransformationComponent(int rx, int ry, int rz, float sx, float sy, float sz) {
|
||||
this(rx, ry, rz, sx, sy, sz, 0, 0, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.geysermc.geyser.api.block.custom.nonvanilla;
|
||||
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public record JavaBlockItem(@NonNull String identifier, @NonNegative int javaId, @NonNegative int stackSize) {
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package org.geysermc.geyser.api.block.custom.nonvanilla;
|
||||
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
public interface JavaBlockState {
|
||||
/**
|
||||
* Gets the identifier of the block state
|
||||
*
|
||||
* @return the identifier of the block state
|
||||
*/
|
||||
@NonNull String identifier();
|
||||
|
||||
/**
|
||||
* Gets the Java ID of the block state
|
||||
*
|
||||
* @return the Java ID of the block state
|
||||
*/
|
||||
@NonNegative int javaId();
|
||||
|
||||
/**
|
||||
* Gets the state group ID of the block state
|
||||
*
|
||||
* @return the state group ID of the block state
|
||||
*/
|
||||
@NonNegative int stateGroupId();
|
||||
|
||||
/**
|
||||
* Gets the block hardness of the block state
|
||||
*
|
||||
* @return the block hardness of the block state
|
||||
*/
|
||||
@NonNegative float blockHardness();
|
||||
|
||||
/**
|
||||
* Gets whether the block state is waterlogged
|
||||
*
|
||||
* @return whether the block state is waterlogged
|
||||
*/
|
||||
boolean waterlogged();
|
||||
|
||||
/**
|
||||
* Gets the collision of the block state
|
||||
*
|
||||
* @return the collision of the block state
|
||||
*/
|
||||
@NonNull JavaBoundingBox[] collision();
|
||||
|
||||
/**
|
||||
* Gets whether the block state can be broken with hand
|
||||
*
|
||||
* @return whether the block state can be broken with hand
|
||||
*/
|
||||
boolean canBreakWithHand();
|
||||
|
||||
/**
|
||||
* Gets the pick item of the block state
|
||||
*
|
||||
* @return the pick item of the block state
|
||||
*/
|
||||
@Nullable String pickItem();
|
||||
|
||||
/**
|
||||
* Gets the piston behavior of the block state
|
||||
*
|
||||
* @return the piston behavior of the block state
|
||||
*/
|
||||
@Nullable String pistonBehavior();
|
||||
|
||||
/**
|
||||
* Gets whether the block state has block entity
|
||||
*
|
||||
* @return whether the block state has block entity
|
||||
*/
|
||||
boolean hasBlockEntity();
|
||||
|
||||
/**
|
||||
* Creates a new {@link JavaBlockState.Builder} instance
|
||||
*
|
||||
* @return a new {@link JavaBlockState.Builder} instance
|
||||
*/
|
||||
static JavaBlockState.Builder builder() {
|
||||
return GeyserApi.api().provider(JavaBlockState.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
Builder identifier(@NonNull String identifier);
|
||||
|
||||
Builder javaId(@NonNegative int javaId);
|
||||
|
||||
Builder stateGroupId(@NonNegative int stateGroupId);
|
||||
|
||||
Builder blockHardness(@NonNegative float blockHardness);
|
||||
|
||||
Builder waterlogged(boolean waterlogged);
|
||||
|
||||
Builder collision(@NonNull JavaBoundingBox[] collision);
|
||||
|
||||
Builder canBreakWithHand(boolean canBreakWithHand);
|
||||
|
||||
Builder pickItem(@Nullable String pickItem);
|
||||
|
||||
Builder pistonBehavior(@Nullable String pistonBehavior);
|
||||
|
||||
Builder hasBlockEntity(boolean hasBlockEntity);
|
||||
|
||||
JavaBlockState build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.geysermc.geyser.api.block.custom.nonvanilla;
|
||||
|
||||
public record JavaBoundingBox(double middleX, double middleY, double middleZ, double sizeX, double sizeY, double sizeZ) {
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.property;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used to store a property of a custom block of a generic type.
|
||||
*/
|
||||
public interface CustomBlockProperty<T> {
|
||||
/**
|
||||
* Gets the name of the property
|
||||
*
|
||||
* @return The name of the property.
|
||||
*/
|
||||
@NonNull String name();
|
||||
|
||||
/**
|
||||
* Gets the values of the property
|
||||
*
|
||||
* @return The values of the property.
|
||||
*/
|
||||
@NonNull List<T> values();
|
||||
|
||||
/**
|
||||
* Gets the type of the property
|
||||
*
|
||||
* @return The type of the property.
|
||||
*/
|
||||
@NonNull PropertyType type();
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.block.custom.property;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* This class is used to define a custom block property's type.
|
||||
*/
|
||||
public class PropertyType {
|
||||
private static final PropertyType BOOLEAN = new PropertyType(Boolean.class);
|
||||
private static final PropertyType INTEGER = new PropertyType(Integer.class);
|
||||
private static final PropertyType STRING = new PropertyType(String.class);
|
||||
|
||||
/**
|
||||
* Gets the property type for a boolean.
|
||||
*
|
||||
* @return The property type for a boolean.
|
||||
*/
|
||||
@NonNull public static PropertyType booleanProp() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property type for an integer.
|
||||
*
|
||||
* @return The property type for an integer.
|
||||
*/
|
||||
@NonNull public static PropertyType integerProp() {
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property type for a string.
|
||||
*
|
||||
* @return The property type for a string.
|
||||
*/
|
||||
@NonNull public static PropertyType stringProp() {
|
||||
return STRING;
|
||||
}
|
||||
|
||||
private final Class<?> typeClass;
|
||||
|
||||
/**
|
||||
* Gets the class of the property type
|
||||
*
|
||||
* @return The class of the property type.
|
||||
*/
|
||||
@NonNull public Class<?> typeClass() {
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
private PropertyType(Class<?> typeClass) {
|
||||
this.typeClass = typeClass;
|
||||
}
|
||||
}
|
|
@ -29,27 +29,107 @@ import org.checkerframework.checker.index.qual.NonNegative;
|
|||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.geyser.api.bedrock.camera.CameraData;
|
||||
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
|
||||
import org.geysermc.geyser.api.command.CommandSource;
|
||||
import org.geysermc.geyser.api.entity.EntityData;
|
||||
import org.geysermc.geyser.api.entity.type.GeyserEntity;
|
||||
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Represents a player connection used in Geyser.
|
||||
*/
|
||||
public interface GeyserConnection extends Connection, CommandSource {
|
||||
|
||||
/**
|
||||
* Exposes the {@link CameraData} for this connection.
|
||||
* It allows you to send fogs, camera shakes, force camera perspectives, and more.
|
||||
*
|
||||
* @return the CameraData for this connection.
|
||||
*/
|
||||
@NonNull CameraData camera();
|
||||
|
||||
/**
|
||||
* Exposes the {@link EntityData} for this connection.
|
||||
* It allows you to get entities by their Java entity ID, show emotes, and get the player entity.
|
||||
*
|
||||
* @return the EntityData for this connection.
|
||||
*/
|
||||
@NonNull EntityData entities();
|
||||
|
||||
/**
|
||||
* @param javaId the Java entity ID to look up.
|
||||
* @return a {@link GeyserEntity} if present in this connection's entity tracker.
|
||||
* @deprecated Use {@link EntityData#entityByJavaId(int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
@NonNull
|
||||
CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId);
|
||||
|
||||
/**
|
||||
* Displays a player entity as emoting to this client.
|
||||
*
|
||||
* @param emoter the player entity emoting.
|
||||
* @param emoteId the emote ID to send to the client.
|
||||
* @param emoteId the emote ID to send to this client.
|
||||
* @deprecated use {@link EntityData#showEmote(GeyserPlayerEntity, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId);
|
||||
|
||||
/**
|
||||
* Shakes the client's camera.
|
||||
* <p>
|
||||
* If the camera is already shaking with the same {@link CameraShake} type, then the additional intensity
|
||||
* will be layered on top of the existing intensity, with their own distinct durations.<br>
|
||||
* If the existing shake type is different and the new intensity/duration are not positive, the existing shake only
|
||||
* switches to the new type. Otherwise, the existing shake is completely overridden.
|
||||
*
|
||||
* @param intensity the intensity of the shake. The client has a maximum total intensity of 4.
|
||||
* @param duration the time in seconds that the shake will occur for
|
||||
* @param type the type of shake
|
||||
*
|
||||
* @deprecated Use {@link CameraData#shakeCamera(float, float, CameraShake)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void shakeCamera(float intensity, float duration, @NonNull CameraShake type);
|
||||
|
||||
/**
|
||||
* Stops all camera shake of any type.
|
||||
*
|
||||
* @deprecated Use {@link CameraData#stopCameraShake()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void stopCameraShake();
|
||||
|
||||
/**
|
||||
* Adds the given fog IDs to the fog cache, then sends all fog IDs in the cache to the client.
|
||||
* <p>
|
||||
* Fog IDs can be found <a href="https://wiki.bedrock.dev/documentation/fog-ids.html">here</a>
|
||||
*
|
||||
* @param fogNameSpaces the fog IDs to add. If empty, the existing cached IDs will still be sent.
|
||||
* @deprecated Use {@link CameraData#sendFog(String...)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void sendFog(String... fogNameSpaces);
|
||||
|
||||
/**
|
||||
* Removes the given fog IDs from the fog cache, then sends all fog IDs in the cache to the client.
|
||||
*
|
||||
* @param fogNameSpaces the fog IDs to remove. If empty, all fog IDs will be removed.
|
||||
* @deprecated Use {@link CameraData#removeFog(String...)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void removeFog(String... fogNameSpaces);
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of all fog affects currently applied to this client.
|
||||
*
|
||||
* @deprecated Use {@link CameraData#fogEffects()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NonNull
|
||||
Set<String> fogEffects();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.entity;
|
||||
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.entity.type.GeyserEntity;
|
||||
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* This class holds all the methods that relate to entities.
|
||||
* Can be accessed through {@link GeyserConnection#entities()}.
|
||||
*/
|
||||
public interface EntityData {
|
||||
|
||||
/**
|
||||
* Returns a {@link GeyserEntity} to e.g. make them play an emote.
|
||||
*
|
||||
* @param javaId the Java entity ID to look up
|
||||
* @return a {@link GeyserEntity} if present in this connection's entity tracker
|
||||
*/
|
||||
@NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId);
|
||||
|
||||
/**
|
||||
* Displays a player entity as emoting to this client.
|
||||
*
|
||||
* @param emoter the player entity emoting
|
||||
* @param emoteId the emote ID to send to this client
|
||||
*/
|
||||
void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId);
|
||||
|
||||
/**
|
||||
* Gets the {@link GeyserPlayerEntity} of this connection.
|
||||
*
|
||||
* @return the {@link GeyserPlayerEntity} of this connection
|
||||
*/
|
||||
@NonNull GeyserPlayerEntity playerEntity();
|
||||
|
||||
/**
|
||||
* (Un)locks the client's movement inputs, so that they cannot move.
|
||||
* To ensure that movement is only unlocked when all locks are released, you must supply
|
||||
* a UUID with this method, and use the same UUID to unlock the camera.
|
||||
*
|
||||
* @param lock whether to lock the movement
|
||||
* @param owner the owner of the lock
|
||||
* @return if the movement is locked after this method call
|
||||
*/
|
||||
boolean lockMovement(boolean lock, @NonNull UUID owner);
|
||||
|
||||
/**
|
||||
* Returns whether the client's movement is currently locked.
|
||||
*
|
||||
* @return whether the movement is locked
|
||||
*/
|
||||
boolean isMovementLocked();
|
||||
}
|
|
@ -25,7 +25,15 @@
|
|||
|
||||
package org.geysermc.geyser.api.entity.type.player;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.api.entity.type.GeyserEntity;
|
||||
|
||||
public interface GeyserPlayerEntity extends GeyserEntity {
|
||||
|
||||
/**
|
||||
* Gets the position of the player.
|
||||
*
|
||||
* @return the position of the player.
|
||||
*/
|
||||
Vector3f position();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ package org.geysermc.geyser.api.event;
|
|||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.event.Event;
|
||||
import org.geysermc.event.bus.OwnedEventBus;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.api.event;
|
|||
|
||||
import org.geysermc.event.Event;
|
||||
import org.geysermc.event.subscribe.OwnedSubscriber;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
|
||||
/**
|
||||
* Represents a subscribed listener to a {@link Event}. Wraps around
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.bedrock;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
||||
|
||||
/**
|
||||
* Called when a Geyser session disconnects.
|
||||
*/
|
||||
public class SessionDisconnectEvent extends ConnectionEvent {
|
||||
private String disconnectReason;
|
||||
|
||||
public SessionDisconnectEvent(@NonNull GeyserConnection connection, @NonNull String reason) {
|
||||
super(connection);
|
||||
this.disconnectReason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the disconnect reason.
|
||||
*
|
||||
* @return the reason for the disconnect
|
||||
*/
|
||||
public @NonNull String disconnectReason() {
|
||||
return disconnectReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the disconnect reason, thereby overriding th original reason.
|
||||
*
|
||||
* @param disconnectReason the reason for the disconnect
|
||||
*/
|
||||
public void disconnectReason(@NonNull String disconnectReason) {
|
||||
this.disconnectReason = disconnectReason;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.bedrock;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
||||
|
||||
/**
|
||||
* Called when Geyser session connected to a Java remote server and is in a play-ready state.
|
||||
*/
|
||||
public final class SessionJoinEvent extends ConnectionEvent {
|
||||
public SessionJoinEvent(@NonNull GeyserConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.bedrock;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
||||
import org.geysermc.geyser.api.pack.ResourcePack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Called when Geyser initializes a session for a new Bedrock client and is in the process of sending resource packs.
|
||||
*/
|
||||
public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent {
|
||||
public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unmodifiable list of {@link ResourcePack}s that will be sent to the client.
|
||||
*
|
||||
* @return an unmodifiable list of resource packs that will be sent to the client.
|
||||
*/
|
||||
public abstract @NonNull List<ResourcePack> resourcePacks();
|
||||
|
||||
/**
|
||||
* Registers a {@link ResourcePack} to be sent to the client.
|
||||
*
|
||||
* @param resourcePack a resource pack that will be sent to the client.
|
||||
* @return true if the resource pack was added successfully,
|
||||
* or false if already present
|
||||
*/
|
||||
public abstract boolean register(@NonNull ResourcePack resourcePack);
|
||||
|
||||
/**
|
||||
* Unregisters a resource pack from being sent to the client.
|
||||
*
|
||||
* @param uuid the UUID of the resource pack
|
||||
* @return true whether the resource pack was removed from the list of resource packs.
|
||||
*/
|
||||
public abstract boolean unregister(@NonNull UUID uuid);
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.bedrock;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.event.Cancellable;
|
||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
||||
import org.geysermc.geyser.api.network.RemoteServer;
|
||||
|
||||
/**
|
||||
* Called when a session has logged in, and is about to connect to a remote java server.
|
||||
* This event is cancellable, and can be used to prevent the player from connecting to the remote server.
|
||||
*/
|
||||
public final class SessionLoginEvent extends ConnectionEvent implements Cancellable {
|
||||
private RemoteServer remoteServer;
|
||||
private boolean cancelled;
|
||||
private String disconnectReason;
|
||||
|
||||
public SessionLoginEvent(@NonNull GeyserConnection connection, @NonNull RemoteServer remoteServer) {
|
||||
super(connection);
|
||||
this.remoteServer = remoteServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the event is cancelled.
|
||||
*
|
||||
* @return The cancel status of the event.
|
||||
*/
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the login event, and disconnects the player.
|
||||
* If cancelled, the player disconnects without connecting to the remote server.
|
||||
* This method will use a default disconnect reason. To specify one, use {@link #setCancelled(boolean, String)}.
|
||||
*
|
||||
* @param cancelled If the login event should be cancelled.
|
||||
*/
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the login event, and disconnects the player with the specified reason.
|
||||
* If cancelled, the player disconnects without connecting to the remote server.
|
||||
*
|
||||
* @param cancelled If the login event should be cancelled.
|
||||
* @param disconnectReason The reason for the cancellation.
|
||||
*/
|
||||
public void setCancelled(boolean cancelled, @NonNull String disconnectReason) {
|
||||
this.cancelled = cancelled;
|
||||
this.disconnectReason = disconnectReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reason for the cancellation, or null if there is no reason given.
|
||||
*
|
||||
* @return The reason for the cancellation.
|
||||
*/
|
||||
public @Nullable String disconnectReason() {
|
||||
return this.disconnectReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link RemoteServer} the section will attempt to connect to.
|
||||
*
|
||||
* @return the {@link RemoteServer} the section will attempt to connect to.
|
||||
*/
|
||||
public @NonNull RemoteServer remoteServer() {
|
||||
return this.remoteServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RemoteServer} to connect the session to.
|
||||
*
|
||||
* @param remoteServer Sets the {@link RemoteServer} to connect to.
|
||||
*/
|
||||
public void remoteServer(@NonNull RemoteServer remoteServer) {
|
||||
this.remoteServer = remoteServer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.connection;
|
||||
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.event.Event;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* Called whenever Geyser gets pinged
|
||||
* <p>
|
||||
* This event allows you to modify/obtain the MOTD, maximum player count, and current number of players online,
|
||||
* Geyser will reply to the client with what was given.
|
||||
*/
|
||||
public interface GeyserBedrockPingEvent extends Event {
|
||||
|
||||
/**
|
||||
* Sets the given string as the primary motd, the given string cannot be null.
|
||||
*
|
||||
* @param primary the string to set as the primary motd
|
||||
*/
|
||||
void primaryMotd(@NonNull String primary);
|
||||
|
||||
/**
|
||||
* Sets the given string as the secondary motd, the given string cannot be null.
|
||||
* Note: the secondary motd is only used for the LAN game entry.
|
||||
*
|
||||
* @param secondary the string to set as the secondary motd
|
||||
*/
|
||||
void secondaryMotd(@NonNull String secondary);
|
||||
|
||||
/**
|
||||
* Sets how many players are currently online, the given number cannot be below 0.
|
||||
*
|
||||
* @param count the number to set
|
||||
*/
|
||||
void playerCount(int count);
|
||||
|
||||
/**
|
||||
* Sets the maximum number of players that can join this server, the given number cannot be below 1.
|
||||
*
|
||||
* @param max the number to set
|
||||
*/
|
||||
void maxPlayerCount(int max);
|
||||
|
||||
/**
|
||||
* Gets the primary motd.
|
||||
*
|
||||
* @return the primary motd string
|
||||
*/
|
||||
@Nullable
|
||||
String primaryMotd();
|
||||
|
||||
/**
|
||||
* Gets the secondary motd.
|
||||
*
|
||||
* @return the secondary motd string
|
||||
*/
|
||||
@Nullable
|
||||
String secondaryMotd();
|
||||
|
||||
/**
|
||||
* Gets the current number of players.
|
||||
*
|
||||
* @return number of players online
|
||||
*/
|
||||
@NonNegative
|
||||
int playerCount();
|
||||
|
||||
/**
|
||||
* Gets the maximum number of players that can join this server
|
||||
*
|
||||
* @return maximum number of players that can join
|
||||
*/
|
||||
int maxPlayerCount();
|
||||
|
||||
/**
|
||||
* Gets the {@link InetSocketAddress} of the client pinging us.
|
||||
*
|
||||
* @return a {@link InetSocketAddress}
|
||||
*/
|
||||
@NonNull
|
||||
InetSocketAddress address();
|
||||
}
|
|
@ -33,7 +33,7 @@ import java.util.Map;
|
|||
|
||||
/**
|
||||
* Called when commands are defined within Geyser.
|
||||
*
|
||||
* <p>
|
||||
* This event allows you to register new commands using the {@link #register(Command)}
|
||||
* method and retrieve the default commands defined.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.lifecycle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
|
||||
import org.geysermc.event.Event;
|
||||
|
||||
/**
|
||||
* Called on Geyser's startup when looking for custom blocks. Custom blocks must be registered through this event.
|
||||
* <p>
|
||||
* This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config.
|
||||
*/
|
||||
public abstract class GeyserDefineCustomBlocksEvent implements Event {
|
||||
/**
|
||||
* Registers the given {@link CustomBlockData} as a custom block
|
||||
*
|
||||
* @param customBlockData the custom block to register
|
||||
*/
|
||||
public abstract void register(@NonNull CustomBlockData customBlockData);
|
||||
|
||||
/**
|
||||
* Registers the given {@link CustomBlockState} as an override for the
|
||||
* given java state identifier
|
||||
* Java state identifiers are listed
|
||||
* <a href="https://raw.githubusercontent.com/GeyserMC/mappings/master/blocks.json">here</a>
|
||||
*
|
||||
* @param javaIdentifier the java state identifier to override
|
||||
* @param customBlockState the custom block state with which to override java state identifier
|
||||
*/
|
||||
public abstract void registerOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState);
|
||||
|
||||
/**
|
||||
* Registers the given {@link CustomBlockData} as an override for the
|
||||
* given java item identifier
|
||||
*
|
||||
* @param javaIdentifier the java item identifier to override
|
||||
* @param customBlockData the custom block data with which to override java item identifier
|
||||
*/
|
||||
public abstract void registerItemOverride(@NonNull String javaIdentifier, @NonNull CustomBlockData customBlockData);
|
||||
|
||||
/**
|
||||
* Registers the given {@link CustomBlockState} as an override for the
|
||||
* given {@link JavaBlockState}
|
||||
*
|
||||
* @param javaBlockState the java block state for the non-vanilla block
|
||||
* @param customBlockState the custom block state with which to override java state identifier
|
||||
*/
|
||||
public abstract void registerOverride(@NonNull JavaBlockState javaBlockState, @NonNull CustomBlockState customBlockState);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.geysermc.geyser.api.event.lifecycle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.event.Event;
|
||||
|
||||
/**
|
||||
* Called on Geyser's startup when looking for custom skulls. Custom skulls must be registered through this event.
|
||||
* <p>
|
||||
* This event will not be called if the "add-non-bedrock-items" setting is disabled in the Geyser config.
|
||||
*/
|
||||
public abstract class GeyserDefineCustomSkullsEvent implements Event {
|
||||
/**
|
||||
* The type of texture provided
|
||||
*/
|
||||
public enum SkullTextureType {
|
||||
USERNAME,
|
||||
UUID,
|
||||
PROFILE,
|
||||
SKIN_HASH
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given username, UUID, base64 encoded profile, or skin hash as a custom skull blocks
|
||||
* @param texture the username, UUID, base64 encoded profile, or skin hash
|
||||
* @param type the type of texture provided
|
||||
*/
|
||||
public abstract void register(@NonNull String texture, @NonNull SkullTextureType type);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.lifecycle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.event.Event;
|
||||
import org.geysermc.geyser.api.event.EventBus;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.extension.ExtensionManager;
|
||||
|
||||
/**
|
||||
* Called when Geyser finished reloading and is accepting Bedrock connections again.
|
||||
* Equivalent to the {@link GeyserPostInitializeEvent}
|
||||
*
|
||||
* @param extensionManager the extension manager
|
||||
* @param eventBus the event bus
|
||||
*/
|
||||
public record GeyserPostReloadEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus<EventRegistrar> eventBus) implements Event {
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.event.lifecycle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.event.Event;
|
||||
import org.geysermc.geyser.api.event.EventBus;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.extension.ExtensionManager;
|
||||
|
||||
/**
|
||||
* Called when Geyser is about to reload. Primarily aimed at extensions, so they can decide on their own what to reload.
|
||||
* After this event is fired, some lifecycle events can be fired again - such as the {@link GeyserLoadResourcePacksEvent}.
|
||||
*
|
||||
* @param extensionManager the extension manager
|
||||
* @param eventBus the event bus
|
||||
*/
|
||||
public record GeyserPreReloadEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus<EventRegistrar> eventBus) implements Event {
|
||||
}
|
|
@ -136,4 +136,12 @@ public interface Extension extends EventRegistrar {
|
|||
default GeyserApi geyserApi() {
|
||||
return GeyserApi.api();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the extension.
|
||||
*/
|
||||
default void disable() {
|
||||
this.setEnabled(false);
|
||||
this.eventBus().unregisterAll();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ import java.util.Collection;
|
|||
public abstract class ExtensionManager {
|
||||
|
||||
/**
|
||||
* Gets an extension with the given name.
|
||||
* Gets an extension by the given ID.
|
||||
*
|
||||
* @param name the name of the extension
|
||||
* @return an extension with the given name
|
||||
* @param id the ID of the extension
|
||||
* @return an extension with the given ID
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Extension extension(@NonNull String name);
|
||||
public abstract Extension extension(@NonNull String id);
|
||||
|
||||
/**
|
||||
* Enables the given {@link Extension}.
|
||||
|
|
|
@ -25,10 +25,16 @@
|
|||
|
||||
package org.geysermc.geyser.api.extension.exception;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* Thrown when an extension's description is invalid.
|
||||
*/
|
||||
public class InvalidDescriptionException extends Exception {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidDescriptionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
@ -25,10 +25,16 @@
|
|||
|
||||
package org.geysermc.geyser.api.extension.exception;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* Thrown when an extension is invalid.
|
||||
*/
|
||||
public class InvalidExtensionException extends Exception {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidExtensionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This is used to store data for a custom item.
|
||||
*/
|
||||
|
@ -75,6 +78,20 @@ public interface CustomItemData {
|
|||
*/
|
||||
boolean displayHandheld();
|
||||
|
||||
/**
|
||||
* Gets the item's creative category, or tab id.
|
||||
*
|
||||
* @return the item's creative category
|
||||
*/
|
||||
@NonNull OptionalInt creativeCategory();
|
||||
|
||||
/**
|
||||
* Gets the item's creative group.
|
||||
*
|
||||
* @return the item's creative group
|
||||
*/
|
||||
@Nullable String creativeGroup();
|
||||
|
||||
/**
|
||||
* Gets the item's texture size. This is to resize the item if the texture is not 16x16.
|
||||
*
|
||||
|
@ -89,6 +106,14 @@ public interface CustomItemData {
|
|||
*/
|
||||
@Nullable CustomRenderOffsets renderOffsets();
|
||||
|
||||
/**
|
||||
* Gets the item's set of tags that can be used in Molang.
|
||||
* Equivalent to "tag:some_tag"
|
||||
*
|
||||
* @return the item's tags, if they exist
|
||||
*/
|
||||
@NonNull Set<String> tags();
|
||||
|
||||
static CustomItemData.Builder builder() {
|
||||
return GeyserApi.api().provider(CustomItemData.Builder.class);
|
||||
}
|
||||
|
@ -109,10 +134,16 @@ public interface CustomItemData {
|
|||
|
||||
Builder displayHandheld(boolean displayHandheld);
|
||||
|
||||
Builder creativeCategory(int creativeCategory);
|
||||
|
||||
Builder creativeGroup(@Nullable String creativeGroup);
|
||||
|
||||
Builder textureSize(int textureSize);
|
||||
|
||||
Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets);
|
||||
|
||||
Builder tags(@Nullable Set<String> tags);
|
||||
|
||||
CustomItemData build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -65,6 +64,14 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
*/
|
||||
int maxDamage();
|
||||
|
||||
/**
|
||||
* Gets the attack damage of the item.
|
||||
* This is purely visual, and only applied to tools
|
||||
*
|
||||
* @return the attack damage of the item
|
||||
*/
|
||||
int attackDamage();
|
||||
|
||||
/**
|
||||
* Gets the tool type of the item.
|
||||
*
|
||||
|
@ -107,20 +114,6 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
*/
|
||||
@Nullable Set<String> repairMaterials();
|
||||
|
||||
/**
|
||||
* Gets the item's creative category, or tab id.
|
||||
*
|
||||
* @return the item's creative category
|
||||
*/
|
||||
@NonNull OptionalInt creativeCategory();
|
||||
|
||||
/**
|
||||
* Gets the item's creative group.
|
||||
*
|
||||
* @return the item's creative group
|
||||
*/
|
||||
@Nullable String creativeGroup();
|
||||
|
||||
/**
|
||||
* Gets if the item is a hat. This is used to determine if the item should be rendered on the player's head, and
|
||||
* normally allow the player to equip it. This is not meant for armor.
|
||||
|
@ -129,6 +122,34 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
*/
|
||||
boolean isHat();
|
||||
|
||||
/**
|
||||
* Gets if the item is a foil. This is used to determine if the item should be rendered with an enchantment glint effect.
|
||||
*
|
||||
* @return if the item is a foil
|
||||
*/
|
||||
boolean isFoil();
|
||||
|
||||
/**
|
||||
* Gets if the item is edible.
|
||||
*
|
||||
* @return if the item is edible
|
||||
*/
|
||||
boolean isEdible();
|
||||
|
||||
/**
|
||||
* Gets if the food item can always be eaten.
|
||||
*
|
||||
* @return if the item is allowed to be eaten all the time
|
||||
*/
|
||||
boolean canAlwaysEat();
|
||||
|
||||
/**
|
||||
* Gets if the item is chargable, like a bow.
|
||||
*
|
||||
* @return if the item should act like a chargable item
|
||||
*/
|
||||
boolean isChargeable();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #displayHandheld()} instead.
|
||||
* Gets if the item is a tool. This is used to set the render type of the item, if the item is handheld.
|
||||
|
@ -156,6 +177,8 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
|
||||
Builder maxDamage(int maxDamage);
|
||||
|
||||
Builder attackDamage(int attackDamage);
|
||||
|
||||
Builder toolType(@Nullable String toolType);
|
||||
|
||||
Builder toolTier(@Nullable String toolTier);
|
||||
|
@ -168,12 +191,16 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
|
||||
Builder repairMaterials(@Nullable Set<String> repairMaterials);
|
||||
|
||||
Builder creativeCategory(int creativeCategory);
|
||||
|
||||
Builder creativeGroup(@Nullable String creativeGroup);
|
||||
|
||||
Builder hat(boolean isHat);
|
||||
|
||||
Builder foil(boolean isFoil);
|
||||
|
||||
Builder edible(boolean isEdible);
|
||||
|
||||
Builder canAlwaysEat(boolean canAlwaysEat);
|
||||
|
||||
Builder chargeable(boolean isChargeable);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #displayHandheld(boolean)} instead.
|
||||
*/
|
||||
|
@ -182,6 +209,12 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
return displayHandheld(isTool);
|
||||
}
|
||||
|
||||
@Override
|
||||
Builder creativeCategory(int creativeCategory);
|
||||
|
||||
@Override
|
||||
Builder creativeGroup(@Nullable String creativeGroup);
|
||||
|
||||
@Override
|
||||
Builder customItemOptions(@NonNull CustomItemOptions customItemOptions);
|
||||
|
||||
|
@ -203,6 +236,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
@Override
|
||||
Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets);
|
||||
|
||||
@Override
|
||||
Builder tags(@Nullable Set<String> tags);
|
||||
|
||||
NonVanillaCustomItemData build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,14 @@ public interface BedrockListener {
|
|||
*/
|
||||
int port();
|
||||
|
||||
/**
|
||||
* Gets the broadcast port that's sent to Bedrock clients with the motd.
|
||||
* This is the port that Bedrock clients will connect with. It usually does not differ from the listening port.
|
||||
*
|
||||
* @return the broadcast port
|
||||
*/
|
||||
int broadcastPort();
|
||||
|
||||
/**
|
||||
* Gets the primary MOTD shown to Bedrock players if a ping passthrough setting is not enabled.
|
||||
* <p>
|
||||
|
|
|
@ -67,4 +67,11 @@ public interface RemoteServer {
|
|||
*/
|
||||
@NonNull
|
||||
AuthType authType();
|
||||
|
||||
/**
|
||||
* Gets if we should attempt to resolve the SRV record for this server.
|
||||
*
|
||||
* @return if we should attempt to resolve the SRV record for this server
|
||||
*/
|
||||
boolean resolveSrv();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.pack;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Represents a pack codec that can be used
|
||||
* to provide resource packs to clients.
|
||||
*/
|
||||
public abstract class PackCodec {
|
||||
|
||||
/**
|
||||
* Gets the sha256 hash of the resource pack.
|
||||
*
|
||||
* @return the hash of the resource pack
|
||||
*/
|
||||
public abstract byte @NonNull [] sha256();
|
||||
|
||||
/**
|
||||
* Gets the resource pack size.
|
||||
*
|
||||
* @return the resource pack file size
|
||||
*/
|
||||
public abstract long size();
|
||||
|
||||
/**
|
||||
* Serializes the given resource pack into a byte buffer.
|
||||
*
|
||||
* @param resourcePack the resource pack to serialize
|
||||
* @return the serialized resource pack
|
||||
*/
|
||||
@NonNull
|
||||
public abstract SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a new resource pack from this codec.
|
||||
*
|
||||
* @return the new resource pack
|
||||
*/
|
||||
@NonNull
|
||||
protected abstract ResourcePack create();
|
||||
|
||||
/**
|
||||
* Creates a new pack provider from the given path.
|
||||
*
|
||||
* @param path the path to create the pack provider from
|
||||
* @return the new pack provider
|
||||
*/
|
||||
@NonNull
|
||||
public static PackCodec path(@NonNull Path path) {
|
||||
return GeyserApi.api().provider(PathPackCodec.class, path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.pack;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Represents a pack codec that creates a resource
|
||||
* pack from a path on the filesystem.
|
||||
*/
|
||||
public abstract class PathPackCodec extends PackCodec {
|
||||
|
||||
/**
|
||||
* Gets the path of the resource pack.
|
||||
*
|
||||
* @return the path of the resource pack
|
||||
*/
|
||||
@NonNull
|
||||
public abstract Path path();
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.pack;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Represents a resource pack sent to Bedrock clients
|
||||
* <p>
|
||||
* This representation of a resource pack only contains what
|
||||
* Geyser requires to send it to the client.
|
||||
*/
|
||||
public interface ResourcePack {
|
||||
|
||||
/**
|
||||
* The {@link PackCodec codec} for this pack.
|
||||
*
|
||||
* @return the codec for this pack
|
||||
*/
|
||||
@NonNull
|
||||
PackCodec codec();
|
||||
|
||||
/**
|
||||
* Gets the resource pack manifest.
|
||||
*
|
||||
* @return the resource pack manifest
|
||||
*/
|
||||
@NonNull
|
||||
ResourcePackManifest manifest();
|
||||
|
||||
/**
|
||||
* Gets the content key of the resource pack. Lack of a content key is represented by an empty String.
|
||||
*
|
||||
* @return the content key of the resource pack
|
||||
*/
|
||||
@NonNull
|
||||
String contentKey();
|
||||
|
||||
/**
|
||||
* Creates a resource pack with the given {@link PackCodec}.
|
||||
*
|
||||
* @param codec the pack codec
|
||||
* @return the resource pack
|
||||
*/
|
||||
@NonNull
|
||||
static ResourcePack create(@NonNull PackCodec codec) {
|
||||
return codec.create();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.pack;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a resource pack manifest.
|
||||
*/
|
||||
public interface ResourcePackManifest {
|
||||
|
||||
/**
|
||||
* Gets the format version of the resource pack.
|
||||
*
|
||||
* @return the format version
|
||||
*/
|
||||
int formatVersion();
|
||||
|
||||
/**
|
||||
* Gets the header of the resource pack.
|
||||
*
|
||||
* @return the header
|
||||
*/
|
||||
@NonNull
|
||||
Header header();
|
||||
|
||||
/**
|
||||
* Gets the modules of the resource pack.
|
||||
*
|
||||
* @return the modules
|
||||
*/
|
||||
@NonNull
|
||||
Collection<? extends Module> modules();
|
||||
|
||||
/**
|
||||
* Gets the dependencies of the resource pack.
|
||||
*
|
||||
* @return the dependencies
|
||||
*/
|
||||
@NonNull
|
||||
Collection<? extends Dependency> dependencies();
|
||||
|
||||
/**
|
||||
* Represents the header of a resource pack.
|
||||
*/
|
||||
interface Header {
|
||||
|
||||
/**
|
||||
* Gets the UUID of the resource pack.
|
||||
*
|
||||
* @return the UUID
|
||||
*/
|
||||
@NonNull
|
||||
UUID uuid();
|
||||
|
||||
/**
|
||||
* Gets the version of the resource pack.
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
@NonNull
|
||||
Version version();
|
||||
|
||||
/**
|
||||
* Gets the name of the resource pack.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@NonNull
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Gets the description of the resource pack.
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
@NonNull
|
||||
String description();
|
||||
|
||||
/**
|
||||
* Gets the minimum supported Minecraft version of the resource pack.
|
||||
*
|
||||
* @return the minimum supported Minecraft version
|
||||
*/
|
||||
@NonNull
|
||||
Version minimumSupportedMinecraftVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a module of a resource pack.
|
||||
*/
|
||||
interface Module {
|
||||
|
||||
/**
|
||||
* Gets the UUID of the module.
|
||||
*
|
||||
* @return the UUID
|
||||
*/
|
||||
@NonNull
|
||||
UUID uuid();
|
||||
|
||||
/**
|
||||
* Gets the version of the module.
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
@NonNull
|
||||
Version version();
|
||||
|
||||
/**
|
||||
* Gets the type of the module.
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
@NonNull
|
||||
String type();
|
||||
|
||||
/**
|
||||
* Gets the description of the module.
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
@NonNull
|
||||
String description();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a dependency of a resource pack.
|
||||
*/
|
||||
interface Dependency {
|
||||
|
||||
/**
|
||||
* Gets the UUID of the dependency.
|
||||
*
|
||||
* @return the uuid
|
||||
*/
|
||||
@NonNull
|
||||
UUID uuid();
|
||||
|
||||
/**
|
||||
* Gets the version of the dependency.
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
@NonNull
|
||||
Version version();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a version of a resource pack.
|
||||
*/
|
||||
interface Version {
|
||||
|
||||
/**
|
||||
* Gets the major version.
|
||||
*
|
||||
* @return the major version
|
||||
*/
|
||||
int major();
|
||||
|
||||
/**
|
||||
* Gets the minor version.
|
||||
*
|
||||
* @return the minor version
|
||||
*/
|
||||
int minor();
|
||||
|
||||
/**
|
||||
* Gets the patch version.
|
||||
*
|
||||
* @return the patch version
|
||||
*/
|
||||
int patch();
|
||||
|
||||
/**
|
||||
* Gets the version formatted as a String.
|
||||
*
|
||||
* @return the version string
|
||||
*/
|
||||
@NonNull String toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Represents the creative menu categories or tabs.
|
||||
*/
|
||||
public enum CreativeCategory {
|
||||
COMMANDS("commands", 1),
|
||||
CONSTRUCTION("construction", 2),
|
||||
EQUIPMENT("equipment", 3),
|
||||
ITEMS("items", 4),
|
||||
NATURE("nature", 5),
|
||||
NONE("none", 6);
|
||||
|
||||
private final String internalName;
|
||||
private final int id;
|
||||
|
||||
CreativeCategory(String internalName, int id) {
|
||||
this.internalName = internalName;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal name of the category.
|
||||
*
|
||||
* @return the name of the category
|
||||
*/
|
||||
public @NonNull String internalName() {
|
||||
return internalName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal ID of the category.
|
||||
*
|
||||
* @return the ID of the category
|
||||
*/
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Represents a Minecraft version.
|
||||
*/
|
||||
public interface MinecraftVersion {
|
||||
|
||||
/**
|
||||
* Gets the Minecraft version as a String.
|
||||
* Example: "1.20.2", or "1.20.40/1.20.41"
|
||||
*
|
||||
* @return the version string
|
||||
*/
|
||||
@NonNull String versionString();
|
||||
|
||||
/**
|
||||
* Gets the protocol version of this Minecraft version.
|
||||
*
|
||||
* @return the protocol version
|
||||
*/
|
||||
int protocolVersion();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.api.util;
|
||||
|
||||
/**
|
||||
* Represents the platform Geyser is running on.
|
||||
*/
|
||||
public record PlatformType(String platformName) {
|
||||
|
||||
@Deprecated
|
||||
public static final PlatformType ANDROID = new PlatformType("Android");
|
||||
public static final PlatformType BUNGEECORD = new PlatformType("BungeeCord");
|
||||
public static final PlatformType FABRIC = new PlatformType("Fabric");
|
||||
public static final PlatformType NEOFORGE = new PlatformType("NeoForge");
|
||||
public static final PlatformType SPIGOT = new PlatformType("Spigot");
|
||||
|
||||
@Deprecated
|
||||
public static final PlatformType SPONGE = new PlatformType("Sponge");
|
||||
public static final PlatformType STANDALONE = new PlatformType("Standalone");
|
||||
public static final PlatformType VELOCITY = new PlatformType("Velocity");
|
||||
public static final PlatformType VIAPROXY = new PlatformType("ViaProxy");
|
||||
}
|
|
@ -30,7 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
|
||||
/**
|
||||
* This is a way to represent a boolean, but with a non set value added.
|
||||
* This class was inspired by adventure's version https://github.com/KyoriPowered/adventure/blob/main/4/api/src/main/java/net/kyori/adventure/util/TriState.java
|
||||
* This class was inspired by adventure's <a href="https://github.com/KyoriPowered/adventure/blob/main/4/api/src/main/java/net/kyori/adventure/util/TriState.java">TriState</a>
|
||||
*/
|
||||
public enum TriState {
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
dependencies {
|
||||
api(projects.core)
|
||||
|
||||
implementation(libs.adventure.text.serializer.bungeecord)
|
||||
compileOnlyApi(libs.bungeecord.proxy)
|
||||
}
|
||||
|
||||
platformRelocate("net.md_5.bungee.jni")
|
||||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("io.netty.channel.kqueue") // This is not used because relocating breaks natives, but we must include it or else we get ClassDefNotFound
|
||||
platformRelocate("net.kyori")
|
||||
platformRelocate("org.yaml") // Broken as of 1.20
|
||||
|
||||
// These dependencies are already present on the platform
|
||||
provided(libs.bungeecord.proxy)
|
||||
|
@ -21,7 +22,6 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
|||
|
||||
dependencies {
|
||||
exclude(dependency("com.google.*:.*"))
|
||||
exclude(dependency("org.yaml:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-native-epoll:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-native-unix-common:.*"))
|
||||
exclude(dependency("io.netty:netty-handler:.*"))
|
||||
|
@ -32,4 +32,4 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
|||
exclude(dependency("io.netty:netty-codec:.*"))
|
||||
exclude(dependency("io.netty:netty-resolver-dns:.*"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,18 +32,26 @@ import net.md_5.bungee.protocol.packet.LoginSuccess;
|
|||
import net.md_5.bungee.protocol.packet.SetCompression;
|
||||
|
||||
public class GeyserBungeeCompressionDisabler extends ChannelOutboundHandlerAdapter {
|
||||
private boolean compressionDisabled = false;
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (!(msg instanceof SetCompression)) {
|
||||
if (msg instanceof LoginSuccess) {
|
||||
// We're past the point that compression can be enabled
|
||||
// Fixes https://github.com/GeyserMC/Geyser/issues/4281
|
||||
// The server may send a LoginDisconnect packet after compression is set.
|
||||
if (!compressionDisabled) {
|
||||
if (ctx.pipeline().get("compress") != null) {
|
||||
ctx.pipeline().remove("compress");
|
||||
compressionDisabled = true;
|
||||
}
|
||||
if (ctx.pipeline().get("decompress") != null) {
|
||||
ctx.pipeline().remove("decompress");
|
||||
compressionDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg instanceof LoginSuccess) {
|
||||
// We're past the point that compression can be enabled
|
||||
ctx.pipeline().remove(this);
|
||||
}
|
||||
super.write(ctx, msg, promise);
|
||||
|
|
|
@ -30,6 +30,7 @@ import net.md_5.bungee.api.ProxyServer;
|
|||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -51,7 +52,8 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
|
|||
this.plugins = new ArrayList<>();
|
||||
|
||||
for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
|
||||
this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort()));
|
||||
InetSocketAddress address = (InetSocketAddress) listener.getSocketAddress();
|
||||
this.listeners.add(new ListenerInfo(address.getHostString(), address.getPort()));
|
||||
}
|
||||
|
||||
for (Plugin plugin : proxy.getPluginManager().getPlugins()) {
|
||||
|
|
|
@ -39,6 +39,7 @@ import net.md_5.bungee.api.plugin.Listener;
|
|||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||
|
@ -125,7 +126,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
|||
.channel(LocalServerChannelWrapper.class)
|
||||
.childHandler(new ChannelInitializer<>() {
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
protected void initChannel(@NonNull Channel ch) throws Exception {
|
||||
if (proxy.getConfig().getServers() == null) {
|
||||
// Proxy hasn't finished loading all plugins - it loads the config after all plugins
|
||||
// Probably doesn't need to be translatable?
|
||||
|
|
|
@ -35,12 +35,12 @@ import net.md_5.bungee.api.connection.PendingConnection;
|
|||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
@ -61,16 +61,11 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
|
|||
}));
|
||||
ProxyPingEvent event = future.join();
|
||||
ServerPing response = event.getResponse();
|
||||
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
|
||||
return new GeyserPingInfo(
|
||||
response.getDescriptionComponent().toLegacyText(),
|
||||
new GeyserPingInfo.Players(response.getPlayers().getMax(), response.getPlayers().getOnline()),
|
||||
new GeyserPingInfo.Version(response.getVersion().getName(), response.getVersion().getProtocol())
|
||||
response.getPlayers().getMax(),
|
||||
response.getPlayers().getOnline()
|
||||
);
|
||||
if (event.getResponse().getPlayers().getSample() != null) {
|
||||
Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer ->
|
||||
geyserPingInfo.getPlayerList().add(proxiedPlayer.getName()));
|
||||
}
|
||||
return geyserPingInfo;
|
||||
}
|
||||
|
||||
// This is static so pending connection can use it
|
||||
|
@ -110,7 +105,7 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List
|
|||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getVirtualHost() {
|
||||
public @Nullable InetSocketAddress getVirtualHost() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,12 +30,13 @@ import net.md_5.bungee.BungeeCord;
|
|||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
|
@ -44,7 +45,6 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
|||
import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -72,12 +72,17 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
onGeyserInitialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGeyserInitialize() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
// Copied from ViaVersion.
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
|
||||
try {
|
||||
ProtocolConstants.class.getField("MINECRAFT_1_19_3");
|
||||
ProtocolConstants.class.getField("MINECRAFT_1_20_3");
|
||||
} catch (NoSuchFieldException e) {
|
||||
getLogger().warning(" / \\");
|
||||
getLogger().warning(" / \\");
|
||||
|
@ -88,35 +93,63 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
getLogger().warning("/_____________\\");
|
||||
}
|
||||
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
|
||||
try {
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
if (!this.loadConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this);
|
||||
this.geyserInjector = new GeyserBungeeInjector(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Remove this in like a year
|
||||
if (getProxy().getPluginManager().getPlugin("floodgate-bungee") != null) {
|
||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/"));
|
||||
// Big hack - Bungee does not provide us an event to listen to, so schedule a repeating
|
||||
// task that waits for a field to be filled which is set after the plugin enable
|
||||
// process is complete
|
||||
this.awaitStartupCompletion(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void awaitStartupCompletion(int tries) {
|
||||
// After 20 tries give up waiting. This will happen just after 3 minutes approximately
|
||||
if (tries >= 20) {
|
||||
this.geyserLogger.warning("BungeeCord plugin startup is taking abnormally long, so Geyser is starting now. " +
|
||||
"If all your plugins are loaded properly, this is a bug! " +
|
||||
"If not, consider cutting down the amount of plugins on your proxy as it is causing abnormally slow starting times.");
|
||||
this.onGeyserEnable();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Field listenersField = BungeeCord.getInstance().getClass().getDeclaredField("listeners");
|
||||
listenersField.setAccessible(true);
|
||||
|
||||
Collection<Channel> listeners = (Collection<Channel>) listenersField.get(BungeeCord.getInstance());
|
||||
if (listeners.isEmpty()) {
|
||||
this.getProxy().getScheduler().schedule(this, this::onGeyserEnable, tries, TimeUnit.SECONDS);
|
||||
} else {
|
||||
this.awaitStartupCompletion(++tries);
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void onGeyserEnable() {
|
||||
if (GeyserImpl.getInstance().isReloading()) {
|
||||
if (!loadConfig()) {
|
||||
return;
|
||||
}
|
||||
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
} else {
|
||||
// For consistency with other platforms - create command manager before GeyserImpl#start()
|
||||
// This ensures the command events are called before the item/block ones are
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
}
|
||||
|
||||
// Force-disable query if enabled, or else Geyser won't enable
|
||||
for (ListenerInfo info : getProxy().getConfig().getListeners()) {
|
||||
if (info.isQueryEnabled() && info.getQueryPort() == geyserConfig.getBedrock().port()) {
|
||||
|
@ -135,48 +168,21 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
}
|
||||
}
|
||||
|
||||
// Big hack - Bungee does not provide us an event to listen to, so schedule a repeating
|
||||
// task that waits for a field to be filled which is set after the plugin enable
|
||||
// process is complete
|
||||
this.awaitStartupCompletion(0);
|
||||
}
|
||||
GeyserImpl.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void awaitStartupCompletion(int tries) {
|
||||
// After 20 tries give up waiting. This will happen
|
||||
// just after 3 minutes approximately
|
||||
if (tries >= 20) {
|
||||
this.geyserLogger.warning("BungeeCord plugin startup is taking abnormally long, so Geyser is starting now. " +
|
||||
"If all your plugins are loaded properly, this is a bug! " +
|
||||
"If not, consider cutting down the amount of plugins on your proxy as it is causing abnormally slow starting times.");
|
||||
this.postStartup();
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
|
||||
}
|
||||
|
||||
// No need to re-register commands or re-init injector when reloading
|
||||
if (GeyserImpl.getInstance().isReloading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Field listenersField = BungeeCord.getInstance().getClass().getDeclaredField("listeners");
|
||||
listenersField.setAccessible(true);
|
||||
|
||||
Collection<Channel> listeners = (Collection<Channel>) listenersField.get(BungeeCord.getInstance());
|
||||
if (listeners.isEmpty()) {
|
||||
this.getProxy().getScheduler().schedule(this, this::postStartup, tries, TimeUnit.SECONDS);
|
||||
} else {
|
||||
this.awaitStartupCompletion(++tries);
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void postStartup() {
|
||||
GeyserImpl.start();
|
||||
|
||||
this.geyserInjector = new GeyserBungeeInjector(this);
|
||||
this.geyserInjector.initializeLocalChannel(this);
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", this.geyser, this.geyserCommandManager.getCommands()));
|
||||
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||
Map<String, Command> commands = entry.getValue();
|
||||
|
@ -186,16 +192,17 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
|
||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(entry.getKey().description().id(), this.geyser, commands));
|
||||
}
|
||||
}
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
|
||||
@Override
|
||||
public void onGeyserDisable() {
|
||||
if (geyser != null) {
|
||||
geyser.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
public void onGeyserShutdown() {
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
}
|
||||
|
@ -204,6 +211,11 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.onGeyserShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserBungeeConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
|
@ -245,7 +257,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
return this.geyserInjector.getServerSocketAddress();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@NonNull
|
||||
@Override
|
||||
public String getServerBindAddress() {
|
||||
return findCompatibleListener().map(InetSocketAddress::getHostString).orElse("");
|
||||
|
@ -271,4 +283,20 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
.map(info -> (InetSocketAddress) info.getSocketAddress())
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
private boolean loadConfig() {
|
||||
try {
|
||||
if (!getDataFolder().exists()) //noinspection ResultOfMethodCallIgnored
|
||||
getDataFolder().mkdir();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import net.kyori.adventure.text.Component;
|
|||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
|
@ -50,7 +51,7 @@ public class BungeeCommandSource implements GeyserCommandSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
public void sendMessage(@NonNull String message) {
|
||||
handle.sendMessage(TextComponent.fromLegacyText(message));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
plugins {
|
||||
id("fabric-loom") version "1.0-SNAPSHOT"
|
||||
id("com.modrinth.minotaur") version "2.+"
|
||||
}
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//to change the versions see the gradle.properties file
|
||||
minecraft(libs.fabric.minecraft)
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation(libs.fabric.loader)
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation(libs.fabric.api)
|
||||
|
||||
// This should be in the libs TOML, but something about modImplementation AND include just doesn't work
|
||||
include(modImplementation("me.lucko", "fabric-permissions-api", "0.2-SNAPSHOT"))
|
||||
|
||||
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
|
||||
// You may need to force-disable transitiveness on them.
|
||||
|
||||
api(projects.core)
|
||||
shadow(projects.core) {
|
||||
exclude(group = "com.google.guava", module = "guava")
|
||||
exclude(group = "com.google.code.gson", module = "gson")
|
||||
exclude(group = "org.slf4j")
|
||||
exclude(group = "com.nukkitx.fastutil")
|
||||
exclude(group = "io.netty.incubator")
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven("https://repo.opencollab.dev/maven-releases/")
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||
maven("https://jitpack.io")
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain")
|
||||
}
|
||||
|
||||
tasks {
|
||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||
// if it is present.
|
||||
// If you remove this task, sources will not be generated.
|
||||
sourcesJar {
|
||||
archiveClassifier.set("sources")
|
||||
from(sourceSets.main.get().allSource)
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
// Mirrors the example fabric project, otherwise tons of dependencies are shaded that shouldn't be
|
||||
configurations = listOf(project.configurations.shadow.get())
|
||||
// The remapped shadowJar is the final desired Geyser-Fabric.jar
|
||||
archiveVersion.set(project.version.toString())
|
||||
archiveClassifier.set("shaded")
|
||||
|
||||
relocate("org.objectweb.asm", "org.geysermc.relocate.asm")
|
||||
relocate("org.yaml", "org.geysermc.relocate.yaml") // https://github.com/CardboardPowered/cardboard/issues/139
|
||||
relocate("com.fasterxml.jackson", "org.geysermc.relocate.jackson")
|
||||
relocate("net.kyori", "org.geysermc.relocate.kyori")
|
||||
|
||||
dependencies {
|
||||
// Exclude everything EXCEPT some DNS stuff required for HAProxy
|
||||
exclude(dependency("io.netty:netty-transport-classes-epoll:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-native-epoll:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-native-unix-common:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-classes-kqueue:.*"))
|
||||
exclude(dependency("io.netty:netty-transport-native-kqueue:.*"))
|
||||
exclude(dependency("io.netty:netty-handler:.*"))
|
||||
exclude(dependency("io.netty:netty-common:.*"))
|
||||
exclude(dependency("io.netty:netty-buffer:.*"))
|
||||
exclude(dependency("io.netty:netty-resolver:.*"))
|
||||
exclude(dependency("io.netty:netty-transport:.*"))
|
||||
exclude(dependency("io.netty:netty-codec:.*"))
|
||||
exclude(dependency("io.netty:netty-resolver-dns:.*"))
|
||||
exclude(dependency("io.netty:netty-resolver-dns-native-macos:.*"))
|
||||
}
|
||||
}
|
||||
|
||||
remapJar {
|
||||
dependsOn(shadowJar)
|
||||
inputFile.set(shadowJar.get().archiveFile)
|
||||
archiveBaseName.set("Geyser-Fabric")
|
||||
archiveClassifier.set("")
|
||||
archiveVersion.set("")
|
||||
}
|
||||
}
|
||||
|
||||
modrinth {
|
||||
token.set(System.getenv("MODRINTH_TOKEN")) // Even though this is the default value, apparently this prevents GitHub Actions caching the token?
|
||||
projectId.set("wKkoqHrH")
|
||||
versionNumber.set(project.version as String + "-" + System.getenv("GITHUB_RUN_NUMBER"))
|
||||
versionType.set("beta")
|
||||
changelog.set("A changelog can be found at https://github.com/GeyserMC/Geyser/commits")
|
||||
|
||||
syncBodyFrom.set(rootProject.file("README.md").readText())
|
||||
|
||||
uploadFile.set(tasks.getByPath("remapJar"))
|
||||
gameVersions.addAll("1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4")
|
||||
|
||||
loaders.add("fabric")
|
||||
|
||||
dependencies {
|
||||
required.project("fabric-api")
|
||||
}
|
||||
}
|
|
@ -1,266 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor;
|
||||
import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
|
||||
private static GeyserFabricMod instance;
|
||||
|
||||
private boolean reloading;
|
||||
|
||||
private GeyserImpl geyser;
|
||||
private ModContainer mod;
|
||||
private Path dataFolder;
|
||||
private MinecraftServer server;
|
||||
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
private GeyserFabricConfiguration geyserConfig;
|
||||
private GeyserFabricLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserPingPassthrough;
|
||||
private WorldManager geyserWorldManager;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
instance = this;
|
||||
mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow();
|
||||
|
||||
this.onEnable();
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
|
||||
// Set as an event so we can get the proper IP and port if needed
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(this::startGeyser);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
dataFolder = FabricLoader.getInstance().getConfigDir().resolve("Geyser-Fabric");
|
||||
if (!dataFolder.toFile().exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
dataFolder.toFile().mkdir();
|
||||
}
|
||||
|
||||
// Init dataFolder first as local language overrides call getConfigFolder()
|
||||
GeyserLocale.init(this);
|
||||
|
||||
try {
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
LogManager.getLogger("geyser-fabric").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
this.geyserLogger = new GeyserFabricLogger(geyserConfig.isDebugMode());
|
||||
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
this.geyser = GeyserImpl.load(PlatformType.FABRIC, this);
|
||||
|
||||
if (server == null) {
|
||||
// Server has yet to start
|
||||
// Register onDisable so players are properly kicked
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onDisable());
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserFabricUpdateListener.onPlayReady(handler));
|
||||
} else {
|
||||
// Server has started and this is a reload
|
||||
startGeyser(this.server);
|
||||
reloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize core Geyser.
|
||||
* A function, as it needs to be called in different places depending on if Geyser is being reloaded or not.
|
||||
*
|
||||
* @param server The minecraft server.
|
||||
*/
|
||||
public void startGeyser(MinecraftServer server) {
|
||||
this.server = server;
|
||||
|
||||
GeyserImpl.start();
|
||||
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
this.geyserWorldManager = new GeyserFabricWorldManager(server);
|
||||
|
||||
// Start command building
|
||||
// Set just "geyser" as the help command
|
||||
GeyserFabricCommandExecutor helpExecutor = new GeyserFabricCommandExecutor(geyser,
|
||||
(GeyserCommand) geyser.commandManager().getCommands().get("help"));
|
||||
LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("geyser").executes(helpExecutor);
|
||||
|
||||
// Register all subcommands as valid
|
||||
for (Map.Entry<String, Command> command : geyser.commandManager().getCommands().entrySet()) {
|
||||
GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(geyser, (GeyserCommand) command.getValue());
|
||||
builder.then(Commands.literal(command.getKey())
|
||||
.executes(executor)
|
||||
// Could also test for Bedrock but depending on when this is called it may backfire
|
||||
.requires(executor::testPermission));
|
||||
}
|
||||
server.getCommands().getDispatcher().register(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
geyser = null;
|
||||
}
|
||||
if (!reloading) {
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserLogger getGeyserLogger() {
|
||||
return geyserLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserCommandManager getGeyserCommandManager() {
|
||||
return geyserCommandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
||||
return geyserPingPassthrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldManager getWorldManager() {
|
||||
return geyserWorldManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigFolder() {
|
||||
return dataFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserFabricDumpInfo(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftServerVersion() {
|
||||
return this.server.getServerVersion();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getServerBindAddress() {
|
||||
return this.server.getLocalIp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPort() {
|
||||
return ((GeyserServerPortGetter) server).geyser$getServerPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testFloodgatePluginPresent() {
|
||||
Optional<ModContainer> floodgate = FabricLoader.getInstance().getModContainer("floodgate");
|
||||
if (floodgate.isPresent()) {
|
||||
geyserConfig.loadFloodgate(this, floodgate.orElse(null));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InputStream getResourceOrNull(String resource) {
|
||||
// We need to handle this differently, because Fabric shares the classloader across multiple mods
|
||||
Path path = this.mod.findPath(resource).orElse(null);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return path.getFileSystem()
|
||||
.provider()
|
||||
.newInputStream(path);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setReloading(boolean reloading) {
|
||||
this.reloading = reloading;
|
||||
}
|
||||
|
||||
public static GeyserFabricMod getInstance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "org.geysermc.geyser.platform.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"client": [
|
||||
"client.IntegratedServerMixin"
|
||||
],
|
||||
"server": [
|
||||
"server.MinecraftDedicatedServerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
15
bootstrap/mod/build.gradle.kts
Normal file
15
bootstrap/mod/build.gradle.kts
Normal file
|
@ -0,0 +1,15 @@
|
|||
architectury {
|
||||
common("neoforge", "fabric")
|
||||
}
|
||||
|
||||
loom {
|
||||
mixin.defaultRefmapName.set("geyser-refmap.json")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.core)
|
||||
compileOnly(libs.mixin)
|
||||
|
||||
// Only here to suppress "unknown enum constant EnvType.CLIENT" warnings. DO NOT USE!
|
||||
compileOnly(libs.fabric.loader)
|
||||
}
|
76
bootstrap/mod/fabric/build.gradle.kts
Normal file
76
bootstrap/mod/fabric/build.gradle.kts
Normal file
|
@ -0,0 +1,76 @@
|
|||
plugins {
|
||||
application
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
fabric()
|
||||
}
|
||||
|
||||
val includeTransitive: Configuration = configurations.getByName("includeTransitive")
|
||||
|
||||
dependencies {
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.fabric.api)
|
||||
|
||||
api(project(":mod", configuration = "namedElements"))
|
||||
shadow(project(path = ":mod", configuration = "transformProductionFabric")) {
|
||||
isTransitive = false
|
||||
}
|
||||
shadow(projects.core) { isTransitive = false }
|
||||
includeTransitive(projects.core)
|
||||
|
||||
// These are NOT transitively included, and instead shadowed + relocated.
|
||||
// Avoids fabric complaining about non-SemVer versioning
|
||||
// TODO: re-evaluate after loom 1.6 (https://github.com/FabricMC/fabric-loom/pull/1075)
|
||||
shadow(libs.protocol.connection) { isTransitive = false }
|
||||
shadow(libs.protocol.common) { isTransitive = false }
|
||||
shadow(libs.protocol.codec) { isTransitive = false }
|
||||
shadow(libs.mcauthlib) { isTransitive = false }
|
||||
shadow(libs.raknet) { isTransitive = false }
|
||||
shadow(libs.netty.codec.haproxy) { isTransitive = false }
|
||||
shadow("org.cloudburstmc:nbt:3.0.2.Final") { isTransitive = false }
|
||||
shadow("io.netty:netty-codec-dns:4.1.103.Final") { isTransitive = false }
|
||||
shadow("io.netty:netty-resolver-dns-classes-macos:4.1.103.Final") { isTransitive = false }
|
||||
|
||||
// Consequences of shading + relocating mcauthlib: shadow/relocate mcpl!
|
||||
shadow(libs.mcprotocollib) { isTransitive = false }
|
||||
|
||||
// Since we also relocate cloudburst protocol: shade erosion common
|
||||
shadow(libs.erosion.common) { isTransitive = false }
|
||||
|
||||
// Permissions
|
||||
modImplementation(libs.fabric.permissions)
|
||||
include(libs.fabric.permissions)
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain")
|
||||
}
|
||||
|
||||
relocate("org.cloudburstmc.nbt")
|
||||
relocate("org.cloudburstmc.netty")
|
||||
relocate("org.cloudburstmc.protocol")
|
||||
relocate("io.netty.handler.codec.dns")
|
||||
relocate("io.netty.handler.codec.haproxy")
|
||||
relocate("io.netty.resolver.dns.macos")
|
||||
relocate("com.github.steveice10.mc.protocol")
|
||||
relocate("com.github.steveice10.mc.auth")
|
||||
relocate("com.github.steveice10.packetlib")
|
||||
|
||||
tasks {
|
||||
remapJar {
|
||||
archiveBaseName.set("Geyser-Fabric")
|
||||
}
|
||||
|
||||
remapModrinthJar {
|
||||
archiveBaseName.set("geyser-fabric")
|
||||
}
|
||||
}
|
||||
|
||||
modrinth {
|
||||
loaders.add("fabric")
|
||||
dependencies {
|
||||
required.project("fabric-api")
|
||||
}
|
||||
}
|
1
bootstrap/mod/fabric/gradle.properties
Normal file
1
bootstrap/mod/fabric/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
|||
loom.platform=fabric
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModUpdateListener;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInitializer {
|
||||
|
||||
public GeyserFabricBootstrap() {
|
||||
super(new GeyserFabricPlatform());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
|
||||
// Set as an event, so we can get the proper IP and port if needed
|
||||
ServerLifecycleEvents.SERVER_STARTED.register((server) -> {
|
||||
this.setServer(server);
|
||||
onGeyserEnable();
|
||||
});
|
||||
}
|
||||
|
||||
// These are only registered once
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onGeyserShutdown());
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserModUpdateListener.onPlayReady(handler.getPlayer()));
|
||||
|
||||
this.onGeyserInitialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) {
|
||||
return Permissions.check(source, permissionNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) {
|
||||
return Permissions.check(source, permissionNode, permissionLevel);
|
||||
}
|
||||
}
|
|
@ -43,21 +43,27 @@ import java.util.stream.Collectors;
|
|||
@Getter
|
||||
public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private String platformVersion = null;
|
||||
private final String platformName;
|
||||
private String platformVersion;
|
||||
private final String minecraftVersion;
|
||||
private final EnvType environmentType;
|
||||
|
||||
@AsteriskSerializer.Asterisk(isIp = true)
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final boolean onlineMode;
|
||||
private final List<ModInfo> mods;
|
||||
|
||||
public GeyserFabricDumpInfo(MinecraftServer server) {
|
||||
this.platformName = server.getServerModName();
|
||||
FabricLoader.getInstance().getModContainer("fabricloader").ifPresent(mod ->
|
||||
this.platformVersion = mod.getMetadata().getVersion().getFriendlyString());
|
||||
|
||||
this.minecraftVersion = server.getServerVersion();
|
||||
this.environmentType = FabricLoader.getInstance().getEnvironmentType();
|
||||
this.serverIP = server.getLocalIp() == null ? "unknown" : server.getLocalIp();
|
||||
this.serverPort = server.getPort();
|
||||
this.onlineMode = server.usesAuthentication();
|
||||
this.mods = new ArrayList<>();
|
||||
|
||||
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
||||
import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GeyserFabricPlatform implements GeyserModPlatform {
|
||||
|
||||
private final ModContainer mod;
|
||||
|
||||
public GeyserFabricPlatform() {
|
||||
this.mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull PlatformType platformType() {
|
||||
return PlatformType.FABRIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String configPath() {
|
||||
return "Geyser-Fabric";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Path dataFolder(@NonNull String modId) {
|
||||
return FabricLoader.getInstance().getConfigDir().resolve(modId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BootstrapDumpInfo dumpInfo(@NonNull MinecraftServer server) {
|
||||
return new GeyserFabricDumpInfo(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) {
|
||||
Optional<ModContainer> floodgate = FabricLoader.getInstance().getModContainer("floodgate");
|
||||
if (floodgate.isPresent()) {
|
||||
Path floodgateDataFolder = FabricLoader.getInstance().getConfigDir().resolve("floodgate");
|
||||
bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InputStream resolveResource(@NonNull String resource) {
|
||||
// We need to handle this differently, because Fabric shares the classloader across multiple mods
|
||||
Path path = this.mod.findPath(resource).orElse(null);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return path.getFileSystem()
|
||||
.provider()
|
||||
.newInputStream(path);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,23 +9,23 @@
|
|||
],
|
||||
"contact": {
|
||||
"website": "${url}",
|
||||
"repo": "https://github.com/GeyserMC/Geyser-Fabric"
|
||||
"repo": "https://github.com/GeyserMC/Geyser"
|
||||
},
|
||||
"license": "MIT",
|
||||
"icon": "assets/geyser-fabric/icon.png",
|
||||
"icon": "assets/geyser/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"org.geysermc.geyser.platform.fabric.GeyserFabricMod"
|
||||
"org.geysermc.geyser.platform.fabric.GeyserFabricBootstrap"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"geyser-fabric.mixins.json"
|
||||
"geyser.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.8",
|
||||
"fabricloader": ">=0.15.2",
|
||||
"fabric": "*",
|
||||
"minecraft": ">=1.19",
|
||||
"minecraft": ">=1.20.4",
|
||||
"fabric-permissions-api-v0": "*"
|
||||
}
|
||||
}
|
51
bootstrap/mod/neoforge/build.gradle.kts
Normal file
51
bootstrap/mod/neoforge/build.gradle.kts
Normal file
|
@ -0,0 +1,51 @@
|
|||
plugins {
|
||||
application
|
||||
}
|
||||
|
||||
// This is provided by "org.cloudburstmc.math.mutable" too, so yeet.
|
||||
// NeoForge's class loader is *really* annoying.
|
||||
provided("org.cloudburstmc.math", "api")
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
neoForge()
|
||||
}
|
||||
|
||||
val includeTransitive: Configuration = configurations.getByName("includeTransitive")
|
||||
|
||||
dependencies {
|
||||
// See https://github.com/google/guava/issues/6618
|
||||
modules {
|
||||
module("com.google.guava:listenablefuture") {
|
||||
replacedBy("com.google.guava:guava", "listenablefuture is part of guava")
|
||||
}
|
||||
}
|
||||
|
||||
neoForge(libs.neoforge.minecraft)
|
||||
|
||||
api(project(":mod", configuration = "namedElements"))
|
||||
shadow(project(path = ":mod", configuration = "transformProductionNeoForge")) {
|
||||
isTransitive = false
|
||||
}
|
||||
shadow(project(path = ":core")) { isTransitive = false }
|
||||
|
||||
includeTransitive(projects.core)
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.forge.GeyserNeoForgeMain")
|
||||
}
|
||||
|
||||
tasks {
|
||||
remapJar {
|
||||
archiveBaseName.set("Geyser-NeoForge")
|
||||
}
|
||||
|
||||
remapModrinthJar {
|
||||
archiveBaseName.set("geyser-neoforge")
|
||||
}
|
||||
}
|
||||
|
||||
modrinth {
|
||||
loaders.add("neoforge")
|
||||
}
|
1
bootstrap/mod/neoforge/gradle.properties
Normal file
1
bootstrap/mod/neoforge/gradle.properties
Normal file
|
@ -0,0 +1 @@
|
|||
loom.platform=neoforge
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStartedEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModUpdateListener;
|
||||
|
||||
@Mod(ModConstants.MOD_ID)
|
||||
public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
|
||||
|
||||
private final GeyserNeoForgePermissionHandler permissionHandler = new GeyserNeoForgePermissionHandler();
|
||||
|
||||
public GeyserNeoForgeBootstrap() {
|
||||
super(new GeyserNeoForgePlatform());
|
||||
|
||||
if (FMLLoader.getDist() == Dist.DEDICATED_SERVER) {
|
||||
// Set as an event so we can get the proper IP and port if needed
|
||||
NeoForge.EVENT_BUS.addListener(this::onServerStarted);
|
||||
}
|
||||
|
||||
NeoForge.EVENT_BUS.addListener(this::onServerStopping);
|
||||
NeoForge.EVENT_BUS.addListener(this::onPlayerJoin);
|
||||
NeoForge.EVENT_BUS.addListener(this.permissionHandler::onPermissionGather);
|
||||
|
||||
this.onGeyserInitialize();
|
||||
}
|
||||
|
||||
private void onServerStarted(ServerStartedEvent event) {
|
||||
this.setServer(event.getServer());
|
||||
this.onGeyserEnable();
|
||||
}
|
||||
|
||||
private void onServerStopping(ServerStoppingEvent event) {
|
||||
this.onGeyserShutdown();
|
||||
}
|
||||
|
||||
private void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
GeyserModUpdateListener.onPlayReady(event.getEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) {
|
||||
return this.permissionHandler.hasPermission(source, permissionNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) {
|
||||
return this.permissionHandler.hasPermission(source, permissionNode, permissionLevel);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.fml.loading.FMLLoader;
|
||||
import net.neoforged.neoforgespi.language.IModInfo;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
public class GeyserNeoForgeDumpInfo extends BootstrapDumpInfo {
|
||||
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final String minecraftVersion;
|
||||
private final Dist dist;
|
||||
|
||||
@AsteriskSerializer.Asterisk(isIp = true)
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final boolean onlineMode;
|
||||
private final List<ModInfo> mods;
|
||||
|
||||
public GeyserNeoForgeDumpInfo(MinecraftServer server) {
|
||||
this.platformName = FMLLoader.launcherHandlerName();
|
||||
this.platformVersion = FMLLoader.versionInfo().neoForgeVersion();
|
||||
this.minecraftVersion = FMLLoader.versionInfo().mcVersion();
|
||||
this.dist = FMLLoader.getDist();
|
||||
this.serverIP = server.getLocalIp() == null ? "unknown" : server.getLocalIp();
|
||||
this.serverPort = server.getPort();
|
||||
this.onlineMode = server.usesAuthentication();
|
||||
this.mods = new ArrayList<>();
|
||||
|
||||
for (IModInfo mod : ModList.get().getMods()) {
|
||||
this.mods.add(new ModInfo(
|
||||
ModList.get().isLoaded(mod.getModId()),
|
||||
mod.getModId(),
|
||||
mod.getVersion().toString(),
|
||||
mod.getModURL().map(URL::toString).orElse("")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class ModInfo {
|
||||
public boolean enabled;
|
||||
public String name;
|
||||
public String version;
|
||||
public String url;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,20 +23,22 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserSpongeMain extends GeyserMain {
|
||||
public class GeyserNeoForgeMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserSpongeMain().displayMessage();
|
||||
new GeyserNeoForgeMain().displayMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginType() {
|
||||
return "Sponge";
|
||||
return "NeoForge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginFolder() {
|
||||
return "mods";
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.neoforge.server.permission.PermissionAPI;
|
||||
import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent;
|
||||
import net.neoforged.neoforge.server.permission.nodes.PermissionDynamicContextKey;
|
||||
import net.neoforged.neoforge.server.permission.nodes.PermissionNode;
|
||||
import net.neoforged.neoforge.server.permission.nodes.PermissionType;
|
||||
import net.neoforged.neoforge.server.permission.nodes.PermissionTypes;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeyserNeoForgePermissionHandler {
|
||||
|
||||
private static final Constructor<?> PERMISSION_NODE_CONSTRUCTOR;
|
||||
|
||||
static {
|
||||
try {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Constructor<PermissionNode> constructor = PermissionNode.class.getDeclaredConstructor(
|
||||
String.class,
|
||||
PermissionType.class,
|
||||
PermissionNode.PermissionResolver.class,
|
||||
PermissionDynamicContextKey[].class
|
||||
);
|
||||
constructor.setAccessible(true);
|
||||
PERMISSION_NODE_CONSTRUCTOR = constructor;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Unable to construct PermissionNode!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, PermissionNode<Boolean>> permissionNodes = new HashMap<>();
|
||||
|
||||
public void onPermissionGather(PermissionGatherEvent.Nodes event) {
|
||||
this.registerNode(Constants.UPDATE_PERMISSION, event);
|
||||
|
||||
GeyserCommandManager commandManager = GeyserImpl.getInstance().commandManager();
|
||||
for (Map.Entry<String, Command> entry : commandManager.commands().entrySet()) {
|
||||
Command command = entry.getValue();
|
||||
|
||||
// Don't register aliases
|
||||
if (!command.name().equals(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.registerNode(command.permission(), event);
|
||||
}
|
||||
|
||||
for (Map<String, Command> commands : commandManager.extensionCommands().values()) {
|
||||
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
||||
Command command = entry.getValue();
|
||||
|
||||
// Don't register aliases
|
||||
if (!command.name().equals(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.registerNode(command.permission(), event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) {
|
||||
PermissionNode<Boolean> node = this.permissionNodes.get(permissionNode);
|
||||
if (node == null) {
|
||||
GeyserImpl.getInstance().getLogger().warning("Unable to find permission node " + permissionNode);
|
||||
return false;
|
||||
}
|
||||
|
||||
return PermissionAPI.getPermission((ServerPlayer) source, node);
|
||||
}
|
||||
|
||||
public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) {
|
||||
if (!source.isPlayer()) {
|
||||
return true;
|
||||
}
|
||||
assert source.getPlayer() != null;
|
||||
boolean permission = this.hasPermission(source.getPlayer(), permissionNode);
|
||||
if (!permission) {
|
||||
return source.getPlayer().hasPermissions(permissionLevel);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void registerNode(String node, PermissionGatherEvent.Nodes event) {
|
||||
PermissionNode<Boolean> permissionNode = this.createNode(node);
|
||||
|
||||
// NeoForge likes to crash if you try and register a duplicate node
|
||||
if (!event.getNodes().contains(permissionNode)) {
|
||||
event.addNodes(permissionNode);
|
||||
this.permissionNodes.put(node, permissionNode);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private PermissionNode<Boolean> createNode(String node) {
|
||||
// The typical constructors in PermissionNode require a
|
||||
// mod id, which means our permission nodes end up becoming
|
||||
// geyser_neoforge.<node> instead of just <node>. We work around
|
||||
// this by using reflection to access the constructor that
|
||||
// doesn't require a mod id or ResourceLocation.
|
||||
try {
|
||||
return (PermissionNode<Boolean>) PERMISSION_NODE_CONSTRUCTOR.newInstance(
|
||||
node,
|
||||
PermissionTypes.BOOLEAN,
|
||||
(PermissionNode.PermissionResolver<Boolean>) (player, playerUUID, context) -> false,
|
||||
new PermissionDynamicContextKey[0]
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to create permission node " + node, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.neoforged.fml.loading.FMLPaths;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
||||
import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class GeyserNeoForgePlatform implements GeyserModPlatform {
|
||||
|
||||
@Override
|
||||
public @NonNull PlatformType platformType() {
|
||||
return PlatformType.NEOFORGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String configPath() {
|
||||
return "Geyser-NeoForge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Path dataFolder(@NonNull String modId) {
|
||||
return FMLPaths.CONFIGDIR.get().resolve(modId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BootstrapDumpInfo dumpInfo(@NonNull MinecraftServer server) {
|
||||
return new GeyserNeoForgeDumpInfo(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) {
|
||||
return false; // No Floodgate mod for NeoForge yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InputStream resolveResource(@NonNull String resource) {
|
||||
return GeyserBootstrap.class.getClassLoader().getResourceAsStream(resource);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
public class ModConstants {
|
||||
public static final String MOD_ID = "geyser_neoforge";
|
||||
}
|
25
bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml
Normal file
25
bootstrap/mod/neoforge/src/main/resources/META-INF/mods.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
modLoader="javafml"
|
||||
loaderVersion="[1,)"
|
||||
license="MIT"
|
||||
[[mods]]
|
||||
modId="geyser_neoforge"
|
||||
version="${version}"
|
||||
displayName="Geyser"
|
||||
displayURL="https://geysermc.org/"
|
||||
logoFile= "../assets/geyser/icon.png"
|
||||
authors="GeyserMC"
|
||||
description="${description}"
|
||||
[[mixins]]
|
||||
config = "geyser.mixins.json"
|
||||
[[dependencies.geyser_neoforge]]
|
||||
modId="neoforge"
|
||||
type="required"
|
||||
versionRange="[20.4.48-beta,)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
[[dependencies.geyser_neoforge]]
|
||||
modId="minecraft"
|
||||
type="required"
|
||||
versionRange="[1.20,1.21)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,16 +23,21 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "^spawner$")
|
||||
public class SpawnerCollision extends SolidCollision {
|
||||
public SpawnerCollision(String params) {
|
||||
super(params);
|
||||
// Increase pushAwayTolerance to work around https://bugs.mojang.com/browse/MCPE-41996
|
||||
pushAwayTolerance = 0.0002;
|
||||
}
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a getter to the server channels in the connection listener class.
|
||||
*/
|
||||
public interface GeyserChannelGetter {
|
||||
|
||||
/**
|
||||
* Returns the channels.
|
||||
*
|
||||
* @return The channels.
|
||||
*/
|
||||
List<ChannelFuture> geyser$getChannels();
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.mod.command.GeyserModCommandExecutor;
|
||||
import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform;
|
||||
import org.geysermc.geyser.platform.mod.world.GeyserModWorldManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class GeyserModBootstrap implements GeyserBootstrap {
|
||||
|
||||
@Getter
|
||||
private static GeyserModBootstrap instance;
|
||||
|
||||
private final GeyserModPlatform platform;
|
||||
|
||||
private GeyserImpl geyser;
|
||||
private Path dataFolder;
|
||||
|
||||
@Setter
|
||||
private MinecraftServer server;
|
||||
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
private GeyserModConfiguration geyserConfig;
|
||||
private GeyserModInjector geyserInjector;
|
||||
private GeyserModLogger geyserLogger;
|
||||
private IGeyserPingPassthrough geyserPingPassthrough;
|
||||
private WorldManager geyserWorldManager;
|
||||
|
||||
@Override
|
||||
public void onGeyserInitialize() {
|
||||
instance = this;
|
||||
dataFolder = this.platform.dataFolder(this.platform.configPath());
|
||||
GeyserLocale.init(this);
|
||||
if (!loadConfig()) {
|
||||
return;
|
||||
}
|
||||
this.geyserLogger = new GeyserModLogger(geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
this.geyser = GeyserImpl.load(this.platform.platformType(), this);
|
||||
|
||||
// Create command manager here, since the permission handler on neo needs it
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
}
|
||||
|
||||
public void onGeyserEnable() {
|
||||
if (GeyserImpl.getInstance().isReloading()) {
|
||||
if (!loadConfig()) {
|
||||
return;
|
||||
}
|
||||
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
}
|
||||
|
||||
GeyserImpl.start();
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserPingPassthrough = new ModPingPassthrough(server, geyserLogger);
|
||||
}
|
||||
|
||||
// No need to re-register commands, or try to re-inject
|
||||
if (GeyserImpl.getInstance().isReloading()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.geyserWorldManager = new GeyserModWorldManager(server);
|
||||
|
||||
// We want to do this late in the server startup process to allow other mods
|
||||
// To do their job injecting, then connect into *that*
|
||||
this.geyserInjector = new GeyserModInjector(server, this.platform);
|
||||
this.geyserInjector.initializeLocalChannel(this);
|
||||
|
||||
// Start command building
|
||||
// Set just "geyser" as the help command
|
||||
GeyserModCommandExecutor helpExecutor = new GeyserModCommandExecutor(geyser,
|
||||
(GeyserCommand) geyser.commandManager().getCommands().get("help"));
|
||||
LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("geyser").executes(helpExecutor);
|
||||
|
||||
// Register all subcommands as valid
|
||||
for (Map.Entry<String, Command> command : geyser.commandManager().getCommands().entrySet()) {
|
||||
GeyserModCommandExecutor executor = new GeyserModCommandExecutor(geyser, (GeyserCommand) command.getValue());
|
||||
builder.then(Commands.literal(command.getKey())
|
||||
.executes(executor)
|
||||
// Could also test for Bedrock but depending on when this is called it may backfire
|
||||
.requires(executor::testPermission)
|
||||
// Allows parsing of arguments; e.g. for /geyser dump logs or the connectiontest command
|
||||
.then(Commands.argument("args", StringArgumentType.greedyString())
|
||||
.executes(context -> executor.runWithArgs(context, StringArgumentType.getString(context, "args")))
|
||||
.requires(executor::testPermission)));
|
||||
}
|
||||
server.getCommands().getDispatcher().register(builder);
|
||||
|
||||
// Register extension commands
|
||||
for (Map.Entry<Extension, Map<String, Command>> extensionMapEntry : geyser.commandManager().extensionCommands().entrySet()) {
|
||||
Map<String, Command> extensionCommands = extensionMapEntry.getValue();
|
||||
if (extensionCommands.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Register help command for just "/<extensionId>"
|
||||
GeyserModCommandExecutor extensionHelpExecutor = new GeyserModCommandExecutor(geyser,
|
||||
(GeyserCommand) extensionCommands.get("help"));
|
||||
LiteralArgumentBuilder<CommandSourceStack> extCmdBuilder = Commands.literal(extensionMapEntry.getKey().description().id()).executes(extensionHelpExecutor);
|
||||
|
||||
for (Map.Entry<String, Command> command : extensionCommands.entrySet()) {
|
||||
GeyserModCommandExecutor executor = new GeyserModCommandExecutor(geyser, (GeyserCommand) command.getValue());
|
||||
extCmdBuilder.then(Commands.literal(command.getKey())
|
||||
.executes(executor)
|
||||
.requires(executor::testPermission)
|
||||
.then(Commands.argument("args", StringArgumentType.greedyString())
|
||||
.executes(context -> executor.runWithArgs(context, StringArgumentType.getString(context, "args")))
|
||||
.requires(executor::testPermission)));
|
||||
}
|
||||
server.getCommands().getDispatcher().register(extCmdBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGeyserDisable() {
|
||||
if (geyser != null) {
|
||||
geyser.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGeyserShutdown() {
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
geyser = null;
|
||||
}
|
||||
if (geyserInjector != null) {
|
||||
geyserInjector.shutdown();
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserModConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserLogger getGeyserLogger() {
|
||||
return geyserLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserCommandManager getGeyserCommandManager() {
|
||||
return geyserCommandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
||||
return geyserPingPassthrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldManager getWorldManager() {
|
||||
return geyserWorldManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigFolder() {
|
||||
return dataFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return this.platform.dumpInfo(this.server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftServerVersion() {
|
||||
return this.server.getServerVersion();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getServerBindAddress() {
|
||||
String ip = this.server.getLocalIp();
|
||||
return ip != null ? ip : ""; // See issue #3812
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPort() {
|
||||
return ((GeyserServerPortGetter) server).geyser$getServerPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testFloodgatePluginPresent() {
|
||||
return this.platform.testFloodgatePluginPresent(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InputStream getResourceOrNull(String resource) {
|
||||
return this.platform.resolveResource(resource);
|
||||
}
|
||||
|
||||
public abstract boolean hasPermission(@NonNull Player source, @NonNull String permissionNode);
|
||||
|
||||
public abstract boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel);
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
private boolean loadConfig() {
|
||||
try {
|
||||
if (!dataFolder.toFile().exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
dataFolder.toFile().mkdir();
|
||||
}
|
||||
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserModConfiguration.class);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
LogManager.getLogger("geyser").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import net.minecraft.network.protocol.login.ClientboundGameProfilePacket;
|
||||
import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket;
|
||||
|
||||
/**
|
||||
* Disables the compression packet (and the compression handlers from being added to the pipeline) for Geyser clients
|
||||
* that won't be receiving the data over the network.
|
||||
* <p>
|
||||
* As of 1.8 - 1.17.1, compression is enabled in the Netty pipeline by adding a listener after a packet is written.
|
||||
* If we simply "cancel" or don't forward the packet, then the listener is never called.
|
||||
*/
|
||||
public class GeyserModCompressionDisabler extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
Class<?> msgClass = msg.getClass();
|
||||
// Don't let any compression packet get through
|
||||
if (!ClientboundLoginCompressionPacket.class.isAssignableFrom(msgClass)) {
|
||||
if (ClientboundGameProfilePacket.class.isAssignableFrom(msgClass)) {
|
||||
|
||||
// We're past the point that a compression packet can be sent, so we can safely yeet ourselves away
|
||||
ctx.channel().pipeline().remove(this);
|
||||
}
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,23 +23,20 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import org.geysermc.geyser.FloodgateKeyLoader;
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class GeyserFabricConfiguration extends GeyserJacksonConfiguration {
|
||||
public class GeyserModConfiguration extends GeyserJacksonConfiguration {
|
||||
@JsonIgnore
|
||||
private Path floodgateKeyPath;
|
||||
|
||||
public void loadFloodgate(GeyserFabricMod geyser, ModContainer floodgate) {
|
||||
public void loadFloodgate(GeyserModBootstrap geyser, Path floodgateDataFolder) {
|
||||
Path geyserDataFolder = geyser.getConfigFolder();
|
||||
Path floodgateDataFolder = floodgate != null ? FabricLoader.getInstance().getConfigDir().resolve("floodgate") : null;
|
||||
|
||||
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataFolder, geyserDataFolder, geyser.getGeyserLogger());
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.DefaultEventLoopGroup;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerConnectionListener;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
||||
import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class GeyserModInjector extends GeyserInjector {
|
||||
|
||||
private final MinecraftServer server;
|
||||
private final GeyserModPlatform platform;
|
||||
private DefaultEventLoopGroup eventLoopGroup;
|
||||
|
||||
/**
|
||||
* Used to uninject ourselves on shutdown.
|
||||
*/
|
||||
private List<ChannelFuture> allServerChannels;
|
||||
|
||||
public GeyserModInjector(MinecraftServer server, GeyserModPlatform platform) {
|
||||
this.server = server;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
|
||||
ServerConnectionListener connection = this.server.getConnection();
|
||||
|
||||
// Find the channel that Minecraft uses to listen to connections
|
||||
ChannelFuture listeningChannel = null;
|
||||
this.allServerChannels = ((GeyserChannelGetter) connection).geyser$getChannels();
|
||||
for (ChannelFuture o : allServerChannels) {
|
||||
listeningChannel = o;
|
||||
break;
|
||||
}
|
||||
|
||||
if (listeningChannel == null) {
|
||||
throw new RuntimeException("Unable to find listening channel!");
|
||||
}
|
||||
|
||||
// Making this a function prevents childHandler from being treated as a non-final variable
|
||||
ChannelInitializer<Channel> childHandler = getChildHandler(bootstrap, listeningChannel);
|
||||
// This method is what initializes the connection in Java Edition, after Netty is all set.
|
||||
Method initChannel = childHandler.getClass().getDeclaredMethod("initChannel", Channel.class);
|
||||
initChannel.setAccessible(true);
|
||||
|
||||
// Separate variable so we can shut it down later
|
||||
eventLoopGroup = new DefaultEventLoopGroup(0, new DefaultThreadFactory("Geyser " + this.platform.platformType().platformName() + " connection thread", Thread.MAX_PRIORITY));
|
||||
ChannelFuture channelFuture = (new ServerBootstrap()
|
||||
.channel(LocalServerChannelWrapper.class)
|
||||
.childHandler(new ChannelInitializer<>() {
|
||||
@Override
|
||||
protected void initChannel(@NonNull Channel ch) throws Exception {
|
||||
initChannel.invoke(childHandler, ch);
|
||||
|
||||
if (bootstrap.getGeyserConfig().isDisableCompression()) {
|
||||
ch.pipeline().addAfter("encoder", "geyser-compression-disabler", new GeyserModCompressionDisabler());
|
||||
}
|
||||
}
|
||||
})
|
||||
// Set to MAX_PRIORITY as MultithreadEventLoopGroup#newDefaultThreadFactory which DefaultEventLoopGroup implements does by default
|
||||
.group(eventLoopGroup)
|
||||
.localAddress(LocalAddress.ANY))
|
||||
.bind()
|
||||
.syncUninterruptibly();
|
||||
// We don't need to add to the list, but plugins like ProtocolSupport and ProtocolLib that add to the main pipeline
|
||||
// will work when we add to the list.
|
||||
allServerChannels.add(channelFuture);
|
||||
this.localChannel = channelFuture;
|
||||
this.serverSocketAddress = channelFuture.channel().localAddress();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ChannelInitializer<Channel> getChildHandler(GeyserBootstrap bootstrap, ChannelFuture listeningChannel) {
|
||||
List<String> names = listeningChannel.channel().pipeline().names();
|
||||
ChannelInitializer<Channel> childHandler = null;
|
||||
for (String name : names) {
|
||||
ChannelHandler handler = listeningChannel.channel().pipeline().get(name);
|
||||
try {
|
||||
Field childHandlerField = handler.getClass().getDeclaredField("childHandler");
|
||||
childHandlerField.setAccessible(true);
|
||||
childHandler = (ChannelInitializer<Channel>) childHandlerField.get(handler);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
if (bootstrap.getGeyserConfig().isDebugMode()) {
|
||||
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (childHandler == null) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
return childHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (this.allServerChannels != null) {
|
||||
this.allServerChannels.remove(this.localChannel);
|
||||
this.allServerChannels = null;
|
||||
}
|
||||
|
||||
if (eventLoopGroup != null) {
|
||||
try {
|
||||
eventLoopGroup.shutdownGracefully().sync();
|
||||
eventLoopGroup = null;
|
||||
} catch (Exception e) {
|
||||
GeyserImpl.getInstance().getLogger().error("Unable to shut down injector! " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
super.shutdown();
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
@ -32,12 +32,12 @@ import org.apache.logging.log4j.Logger;
|
|||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
|
||||
public class GeyserFabricLogger implements GeyserLogger {
|
||||
private final Logger logger = LogManager.getLogger("geyser-fabric");
|
||||
public class GeyserModLogger implements GeyserLogger {
|
||||
private final Logger logger = LogManager.getLogger("geyser");
|
||||
|
||||
private boolean debug;
|
||||
|
||||
public GeyserFabricLogger(boolean isDebug) {
|
||||
public GeyserModLogger(boolean isDebug) {
|
||||
debug = isDebug;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ public class GeyserFabricLogger implements GeyserLogger {
|
|||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
// As of Java Edition 1.19.2, Fabric's console doesn't natively support legacy format
|
||||
// As of Java Edition 1.19.2, Minecraft's console doesn't natively support legacy format
|
||||
String flattened = LegacyComponentSerializer.legacySection().serialize(message);
|
||||
// Add the reset at the end, or else format will persist... forever.
|
||||
// https://cdn.discordapp.com/attachments/573909525132738590/1033904509170225242/unknown.png
|
|
@ -23,21 +23,22 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.platform.fabric.command.FabricCommandSender;
|
||||
import org.geysermc.geyser.platform.mod.command.ModCommandSender;
|
||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||
|
||||
public final class GeyserFabricUpdateListener {
|
||||
public static void onPlayReady(ServerGamePacketListenerImpl handler) {
|
||||
if (Permissions.check(handler.player, Constants.UPDATE_PERMISSION, 2)) {
|
||||
VersionCheckUtils.checkForGeyserUpdate(() -> new FabricCommandSender(handler.player.createCommandSourceStack()));
|
||||
public final class GeyserModUpdateListener {
|
||||
public static void onPlayReady(Player player) {
|
||||
CommandSourceStack stack = player.createCommandSourceStack();
|
||||
if (GeyserModBootstrap.getInstance().hasPermission(stack, Constants.UPDATE_PERMISSION, 2)) {
|
||||
VersionCheckUtils.checkForGeyserUpdate(() -> new ModCommandSender(stack));
|
||||
}
|
||||
}
|
||||
|
||||
private GeyserFabricUpdateListener() {
|
||||
private GeyserModUpdateListener() {
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
package org.geysermc.geyser.platform.mod;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue