1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-23 08:49:23 +00:00

Merge remote-tracking branch 'upstream/master' into feature/new-custom-entity-api

# Conflicts:
#	core/src/main/java/org/geysermc/geyser/GeyserImpl.java
#	core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
#	core/src/main/java/org/geysermc/geyser/registry/Registries.java
#	core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java
#	core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaAddEntityTranslator.java
#	core/src/main/java/org/geysermc/geyser/util/EntityUtils.java
This commit is contained in:
onebeastchris
2025-10-12 21:10:57 +02:00
1005 changed files with 138863 additions and 63920 deletions

View File

@@ -1,8 +1,24 @@
plugins {
// Allow blossom to mark sources root of templates
idea
id("geyser.publish-conventions")
alias(libs.plugins.blossom)
}
dependencies {
api(libs.base.api)
api(libs.math)
}
}
version = property("version")!!
val apiVersion = (version as String).removeSuffix("-SNAPSHOT")
sourceSets {
main {
blossom {
javaSources {
property("version", apiVersion)
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 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;
import org.geysermc.api.util.ApiVersion;
/**
* Not a public API. For internal use only. May change without notice.
* This class is processed before compilation to insert build properties.
*/
class BuildData {
static final String VERSION = "{{ version }}";
static final ApiVersion API_VERSION;
static {
String[] parts = VERSION.split("\\.");
if (parts.length != 3) {
throw new RuntimeException("Invalid api version: " + VERSION);
}
try {
int human = Integer.parseInt(parts[0]);
int major = Integer.parseInt(parts[1]);
int minor = Integer.parseInt(parts[2]);
API_VERSION = new ApiVersion(human, major, minor);
} catch (Exception e) {
throw new RuntimeException("Invalid api version: " + VERSION, e);
}
}
}

View File

@@ -29,6 +29,7 @@ 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.api.util.ApiVersion;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.EventBus;
@@ -169,4 +170,14 @@ public interface GeyserApi extends GeyserApiBase {
static GeyserApi api() {
return Geyser.api(GeyserApi.class);
}
/**
* Returns the {@link ApiVersion} representing the current Geyser api version.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
*
* @return the current geyser api version
*/
default ApiVersion geyserApiVersion() {
return BuildData.API_VERSION;
}
}

View File

@@ -145,4 +145,36 @@ public interface CameraData {
* @return whether the camera is currently locked
*/
boolean isCameraLocked();
}
/**
* Hides a {@link GuiElement} on the client's side.
*
* @param element the {@link GuiElement} to hide
*/
void hideElement(@NonNull GuiElement... element);
/**
* Resets a {@link GuiElement} on the client's side.
* This makes the client decide on its own - e.g. based on client settings -
* whether to show or hide the gui element.
* <p>
* If no elements are specified, this will reset all currently hidden elements
*
* @param element the {@link GuiElement} to reset
*/
void resetElement(@NonNull GuiElement @Nullable... element);
/**
* Determines whether a {@link GuiElement} is currently hidden.
*
* @param element the {@link GuiElement} to check
*/
boolean isHudElementHidden(@NonNull GuiElement element);
/**
* Returns the currently hidden {@link GuiElement}s.
*
* @return an unmodifiable view of all currently hidden {@link GuiElement}s
*/
@NonNull Set<GuiElement> hiddenElements();
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 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.bedrock.camera;
/**
* Represent GUI elements on the players HUD display.
* These can be hidden using {@link CameraData#hideElement(GuiElement...)},
* and one can reset their visibility using {@link CameraData#resetElement(GuiElement...)}.
*/
public class GuiElement {
public static final GuiElement PAPER_DOLL = new GuiElement(0);
public static final GuiElement ARMOR = new GuiElement(1);
public static final GuiElement TOOL_TIPS = new GuiElement(2);
public static final GuiElement TOUCH_CONTROLS = new GuiElement(3);
public static final GuiElement CROSSHAIR = new GuiElement(4);
public static final GuiElement HOTBAR = new GuiElement(5);
public static final GuiElement HEALTH = new GuiElement(6);
public static final GuiElement PROGRESS_BAR = new GuiElement(7);
public static final GuiElement FOOD_BAR = new GuiElement(8);
public static final GuiElement AIR_BUBBLES_BAR = new GuiElement(9);
public static final GuiElement VEHICLE_HEALTH = new GuiElement(10);
public static final GuiElement EFFECTS_BAR = new GuiElement(11);
public static final GuiElement ITEM_TEXT_POPUP = new GuiElement(12);
private GuiElement(int id) {
this.id = id;
}
private final int id;
/**
* Internal use only; don't depend on these values being consistent.
*/
public int id() {
return this.id;
}
}

View File

@@ -1,7 +0,0 @@
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) {
}

View File

@@ -59,7 +59,9 @@ public interface JavaBlockState {
* Gets the pick item of the block state
*
* @return the pick item of the block state
* @deprecated the pick item is sent by the Java server
*/
@Deprecated
@Nullable String pickItem();
/**
@@ -70,10 +72,13 @@ public interface JavaBlockState {
@Nullable String pistonBehavior();
/**
* Gets whether the block state has block entity
* Gets whether the block state has a block entity
*
* @return whether the block state has block entity
* @deprecated Does not have an effect. If you were using this to
* set piston behavior, use {@link #pistonBehavior()} instead.
*/
@Deprecated(forRemoval = true)
boolean hasBlockEntity();
/**
@@ -100,10 +105,16 @@ public interface JavaBlockState {
Builder canBreakWithHand(boolean canBreakWithHand);
@Deprecated
Builder pickItem(@Nullable String pickItem);
Builder pistonBehavior(@Nullable String pistonBehavior);
/**
* @deprecated Does not have an effect. If you were using this to
* * set piston behavior, use {@link #pistonBehavior(String)} instead.
*/
@Deprecated(forRemoval = true)
Builder hasBlockEntity(boolean hasBlockEntity);
JavaBlockState build();

View File

@@ -28,7 +28,9 @@ package org.geysermc.geyser.api.command;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.util.TriState;
import java.util.Collections;
import java.util.List;
@@ -58,15 +60,15 @@ public interface Command {
* Gets the permission node associated with
* this command.
*
* @return the permission node for this command
* @return the permission node for this command if defined, otherwise an empty string
*/
@NonNull
String permission();
/**
* Gets the aliases for this command.
* Gets the aliases for this command, as an unmodifiable list
*
* @return the aliases for this command
* @return the aliases for this command as an unmodifiable list
*/
@NonNull
List<String> aliases();
@@ -75,35 +77,39 @@ public interface Command {
* Gets if this command is designed to be used only by server operators.
*
* @return if this command is designated to be used only by server operators.
* @deprecated this method is not guaranteed to provide meaningful or expected results.
*/
boolean isSuggestedOpOnly();
/**
* Gets if this command is executable on console.
*
* @return if this command is executable on console
*/
boolean isExecutableOnConsole();
/**
* Gets the subcommands associated with this
* command. Mainly used within the Geyser Standalone
* GUI to know what subcommands are supported.
*
* @return the subcommands associated with this command
*/
@NonNull
default List<String> subCommands() {
return Collections.emptyList();
@Deprecated(forRemoval = true)
default boolean isSuggestedOpOnly() {
return false;
}
/**
* Used to send a deny message to Java players if this command can only be used by Bedrock players.
*
* @return true if this command can only be used by Bedrock players.
* @return true if this command is executable on console
* @deprecated use {@link #isPlayerOnly()} instead (inverted)
*/
default boolean isBedrockOnly() {
return false;
@Deprecated(forRemoval = true)
default boolean isExecutableOnConsole() {
return !isPlayerOnly();
}
/**
* @return true if this command can only be used by players
*/
boolean isPlayerOnly();
/**
* @return true if this command can only be used by Bedrock players
*/
boolean isBedrockOnly();
/**
* @deprecated this method will always return an empty immutable list
*/
@Deprecated(forRemoval = true)
@NonNull
default List<String> subCommands() {
return Collections.emptyList();
}
/**
@@ -128,7 +134,7 @@ public interface Command {
* is an instance of this source.
*
* @param sourceType the source type
* @return the builder
* @return this builder
*/
Builder<T> source(@NonNull Class<? extends T> sourceType);
@@ -136,7 +142,7 @@ public interface Command {
* Sets the command name.
*
* @param name the command name
* @return the builder
* @return this builder
*/
Builder<T> name(@NonNull String name);
@@ -144,23 +150,40 @@ public interface Command {
* Sets the command description.
*
* @param description the command description
* @return the builder
* @return this builder
*/
Builder<T> description(@NonNull String description);
/**
* Sets the permission node.
* Sets the permission node required to run this command. <br>
* It will not be registered with any permission registries, such as an underlying server,
* or a permissions Extension (unlike {@link #permission(String, TriState)}).
*
* @param permission the permission node
* @return the builder
* @return this builder
*/
Builder<T> permission(@NonNull String permission);
/**
* Sets the permission node and its default value. The usage of the default value is platform dependant
* and may or may not be used. For example, it may be registered to an underlying server.
* <p>
* Extensions may instead listen for {@link GeyserRegisterPermissionsEvent} to register permissions,
* especially if the same permission is required by multiple commands. Also see this event for TriState meanings.
*
* @param permission the permission node
* @param defaultValue the node's default value
* @return this builder
* @deprecated this method is experimental and may be removed in the future
*/
@Deprecated
Builder<T> permission(@NonNull String permission, @NonNull TriState defaultValue);
/**
* Sets the aliases.
*
* @param aliases the aliases
* @return the builder
* @return this builder
*/
Builder<T> aliases(@NonNull List<String> aliases);
@@ -168,46 +191,62 @@ public interface Command {
* Sets if this command is designed to be used only by server operators.
*
* @param suggestedOpOnly if this command is designed to be used only by server operators
* @return the builder
* @return this builder
* @deprecated this method is not guaranteed to produce meaningful or expected results
*/
@Deprecated(forRemoval = true)
Builder<T> suggestedOpOnly(boolean suggestedOpOnly);
/**
* Sets if this command is executable on console.
*
* @param executableOnConsole if this command is executable on console
* @return the builder
* @return this builder
* @deprecated use {@link #isPlayerOnly()} instead (inverted)
*/
@Deprecated(forRemoval = true)
Builder<T> executableOnConsole(boolean executableOnConsole);
/**
* Sets if this command can only be executed by players.
*
* @param playerOnly if this command is player only
* @return this builder
*/
Builder<T> playerOnly(boolean playerOnly);
/**
* Sets if this command can only be executed by bedrock players.
*
* @param bedrockOnly if this command is bedrock only
* @return this builder
*/
Builder<T> bedrockOnly(boolean bedrockOnly);
/**
* Sets the subcommands.
*
* @param subCommands the subcommands
* @return the builder
* @return this builder
* @deprecated this method has no effect
*/
Builder<T> subCommands(@NonNull List<String> subCommands);
/**
* Sets if this command is bedrock only.
*
* @param bedrockOnly if this command is bedrock only
* @return the builder
*/
Builder<T> bedrockOnly(boolean bedrockOnly);
@Deprecated(forRemoval = true)
default Builder<T> subCommands(@NonNull List<String> subCommands) {
return this;
}
/**
* Sets the {@link CommandExecutor} for this command.
*
* @param executor the command executor
* @return the builder
* @return this builder
*/
Builder<T> executor(@NonNull CommandExecutor<T> executor);
/**
* Builds the command.
*
* @return the command
* @return a new command from this builder
*/
@NonNull
Command build();

View File

@@ -26,6 +26,10 @@
package org.geysermc.geyser.api.command;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.connection.GeyserConnection;
import java.util.UUID;
/**
* Represents an instance capable of sending commands.
@@ -64,6 +68,17 @@ public interface CommandSource {
*/
boolean isConsole();
/**
* @return a Java UUID if this source represents a player, otherwise null
*/
@Nullable UUID playerUuid();
/**
* @return a GeyserConnection if this source represents a Bedrock player that is connected
* to this Geyser instance, otherwise null
*/
@Nullable GeyserConnection connection();
/**
* Returns the locale of the command source.
*

View File

@@ -26,6 +26,7 @@
package org.geysermc.geyser.api.connection;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.api.connection.Connection;
@@ -35,8 +36,11 @@ 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 org.geysermc.geyser.api.skin.SkinData;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
/**
@@ -60,6 +64,108 @@ public interface GeyserConnection extends Connection, CommandSource {
*/
@NonNull EntityData entities();
/**
* Returns the current ping of the connection.
*/
int ping();
/**
* @return {@code true} if the client currently has a form open.
* @since 2.8.0
*/
boolean hasFormOpen();
/**
* Closes the currently open form on the client.
*/
void closeForm();
/**
* Gets the Bedrock protocol version of the player.
*/
int protocolVersion();
/**
* Attempts to open the {@code minecraft:pause_screen_additions} dialog tag. This method opens this dialog the same way Java does, that is:
*
* <ul>
* <li>If there are multiple dialogs in the additions tag, the {@code minecraft:custom_options} dialog is opened to select a dialog.</li>
* <li>If there is one dialog in the additions tag, that dialog is opened.</li>
* <li>If there are no dialogs in the tag, but there are server links sent to the client, the {@code minecraft:server_links} dialog is opened.</li>
* <li>If all of the above fails, no dialog is opened.</li>
* </ul>
*
* <p>Use {@link GeyserConnection#hasFormOpen()} to check if a dialog was opened.</p>
* @since 2.8.0
*/
void openPauseScreenAdditions();
/**
* Attempts to open the {@code minecraft:quick_actions} dialog tag. This method opens this dialog the same way Java does, that is:
*
* <ul>
* <li>If there are multiple dialogs in the actions tag, the {@code minecraft:quick_actions} dialog is opened to select a dialog.</li>
* <li>If there is one dialog in the actions tag, that dialog is opened.</li>
* <li>If there are no dialogs in the tag, no dialog is opened.</li>
* </ul>
*
* <p>Use {@link GeyserConnection#hasFormOpen()} to check if a dialog was opened.</p>
* @since 2.8.0
*/
void openQuickActions();
/**
* Sends a command as if the player had executed it.
*
* @param command the command without the leading forward-slash
* @since 2.8.0
*/
void sendCommand(String command);
/**
* Gets the hostname or ip address the player used to join this Geyser instance.
* Example:
* <ul>
* <li> {@code test.geysermc.org} </li>
* <li> {@code 127.0.0.1} </li>
* <li> {@code 06e9:c755:4eff:5f13:9b4c:4b21:9df2:6a73} </li>
* </ul>
*
* @throws NoSuchElementException if called before the session is fully initialized
* @return the ip address or hostname string the player used to join
* @since 2.8.3
*/
@NonNull
String joinAddress();
/**
* Gets the port the player used to join this Geyser instance.
* Example:
* <ul>
* <li> {@code 19132} </li>
* <li> {@code 2202} </li>
* </ul>
*
* @throws NoSuchElementException if called before the session is fully initialized
* @return the port the player used to join
* @since 2.8.3
*/
@Positive
int joinPort();
/**
* Applies a skin to a player seen by this Geyser connection.
* If the uuid matches the {@link GeyserConnection#javaUuid()}, this
* will update the skin of this Geyser connection.
* If the player uuid provided is not known to this connection, this method
* will silently return.
*
* @param player which player this skin should be applied to
* @param skinData the skin data to apply
* @since 2.8.3
*/
void sendSkin(@NonNull UUID player, @NonNull SkinData skinData);
/**
* @param javaId the Java entity ID to look up.
* @return a {@link GeyserEntity} if present in this connection's entity tracker.

View File

@@ -81,4 +81,10 @@ public interface EntityData {
* @return whether the movement is locked
*/
boolean isMovementLocked();
/**
* Sends a request to the Java server to switch the items in the main and offhand.
* There is no guarantee of the server accepting the request.
*/
void switchHands();
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2025 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.property;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntityPropertiesEvent;
/**
* Collects property changes to be applied as a single, batched update to an entity.
* <p>
* Notes:
* <ul>
* <li>Passing {@code null} as a value resets the property to its default.</li>
* <li>Numeric properties must be within declared ranges; enum properties must use an allowed value.</li>
* <li>Multiple updates to the same property within a single batch will result in the last value being applied.</li>
* <li>The updater is short-lived and should not be retained outside the batching callback.</li>
* </ul>
*
* <pre>{@code
* entity.updatePropertiesBatched(updater -> {
* updater.update(SOME_FLOAT_PROPERTY, 0.15f);
* updater.update(SOME_BOOLEAN_PROPERTY, true);
* updater.update(SOME_INT_PROPERTY, null); // reset to default
* });
* }</pre>
*
* @since 2.9.0
*/
@FunctionalInterface
public interface BatchPropertyUpdater {
/**
* Queues an update for the given property within the current batch.
* <p>
* If {@code value} is {@code null}, the property will be reset to its default value
* as declared when the property was registered during the {@link GeyserDefineEntityPropertiesEvent}.
*
* @param property a {@link GeyserEntityProperty} registered for the target entity type
* @param value the new value, or {@code null} to reset to the default
* @param <T> the property's value type
*
* @since 2.9.0
*/
<T> void update(@NonNull GeyserEntityProperty<T> property, @Nullable T value);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2025 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.property;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.util.Identifier;
/**
* Represents a property that can be attached to an entity.
* <p>
* Entity properties are used to describe metadata about an entity, such as
* integers, floats, booleans, or enums.
* @see <a href="https://learn.microsoft.com/en-us/minecraft/creator/documents/introductiontoentityproperties?view=minecraft-bedrock-stable#number-of-entity-properties-per-entity-type">
* Official documentation for info</a>
*
* @param <T> the type of value stored by this property
*
* @since 2.9.0
*/
public interface GeyserEntityProperty<T> {
/**
* Gets the unique name of this property.
* Custom properties cannot use the vanilla namespace
* to avoid collisions with vanilla entity properties.
*
* @return the property identifier
* @since 2.9.0
*/
@NonNull
Identifier identifier();
/**
* Gets the default value of this property which
* is set upon spawning entities.
*
* @return the default value of this property
* @since 2.9.0
*/
@NonNull
T defaultValue();
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2025 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.property.type;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
/**
* Represents a boolean entity property.
* @since 2.9.0
*/
public interface GeyserBooleanEntityProperty extends GeyserEntityProperty<Boolean> {
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2025 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.property.type;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
/**
* Represents a Java enum-backed enum property.
* There are a few key limitations:
* <ul>
* <li>There cannot be more than 16 values</li>
* <li>Enum names cannot be longer than 32 chars, must start with a letter, and may contain numbers and underscores</li>
* </ul>
*
* @param <E> the enum type
* @since 2.9.0
*/
public interface GeyserEnumEntityProperty<E extends Enum<E>> extends GeyserEntityProperty<E> {
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2025 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.property.type;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntityPropertiesEvent;
import org.geysermc.geyser.api.util.Identifier;
/**
* Represents a float-backed entity property with inclusive bounds.
* Values associated with this property must be always within the {@code [min(), max()]} bounds.
*
* @see GeyserDefineEntityPropertiesEvent#registerFloatProperty(Identifier, Identifier, float, float, Float)
* @since 2.9.0
*/
public interface GeyserFloatEntityProperty extends GeyserEntityProperty<Float> {
/**
* @return the inclusive lower bound for this property
* @since 2.9.0
*/
float min();
/**
* @return the inclusive upper bound for this property
* @since 2.9.0
*/
float max();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 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.property.type;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntityPropertiesEvent;
import org.geysermc.geyser.api.util.Identifier;
/**
* Represents an int-backed entity property with inclusive bounds.
* There are a few key limitations:
* <ul>
* <li>Values must be always within the {@code [min(), max()]} bounds</li>
* <li>Molang evaluation uses floats under the hood; very large integers can lose precision.
* Prefer keeping values in a practical range to avoid rounding issues.</li>
* </ul>
*
* @see GeyserDefineEntityPropertiesEvent#registerIntegerProperty(Identifier, Identifier, int, int, Integer)
* @since 2.9.0
*/
public interface GeyserIntEntityProperty extends GeyserEntityProperty<Integer> {
/**
* @return the inclusive lower bound for this property
* @since 2.9.0
*/
int min();
/**
* @return the inclusive upper bound for this property
* @since 2.9.0
*/
int max();
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 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.property.type;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
import java.util.List;
/**
* Represents a string-backed enum property.
* There are a few key limitations:
* <ul>
* <li>There cannot be more than 16 values</li>
* <li>The values' names cannot be longer than 32 chars, must start with a letter, and may contain numbers and underscores</li>
* </ul>
*
* @since 2.9.0
*/
public interface GeyserStringEnumProperty extends GeyserEntityProperty<String> {
/**
* @return an unmodifiable list of all registered values
* @since 2.9.0
*/
List<String> values();
}

View File

@@ -26,9 +26,17 @@
package org.geysermc.geyser.api.entity.type;
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.property.BatchPropertyUpdater;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntityPropertiesEvent;
import java.util.function.Consumer;
/**
* Represents a unique instance of an entity. Each {@link org.geysermc.geyser.api.connection.GeyserConnection}
* Represents a unique instance of an entity. Each {@link GeyserConnection}
* have their own sets of entities - no two instances will share the same GeyserEntity instance.
*/
public interface GeyserEntity {
@@ -37,4 +45,24 @@ public interface GeyserEntity {
*/
@NonNegative
int javaId();
/**
* Updates an entity property with a new value.
* If the new value is null, the property is reset to the default value.
*
* @param property a {@link GeyserEntityProperty} registered for this type in the {@link GeyserDefineEntityPropertiesEvent}
* @param value the new property value
* @param <T> the type of the value
* @since 2.9.0
*/
default <T> void updateProperty(@NonNull GeyserEntityProperty<T> property, @Nullable T value) {
this.updatePropertiesBatched(consumer -> consumer.update(property, value));
}
/**
* Updates multiple properties with just one update packet.
* @see BatchPropertyUpdater
* @since 2.9.0
*/
void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer);
}

View File

@@ -31,9 +31,9 @@ import org.geysermc.geyser.api.entity.type.GeyserEntity;
public interface GeyserPlayerEntity extends GeyserEntity {
/**
* Gets the position of the player.
* Gets the position of the player, as it is known to the Java server.
*
* @return the position of the player.
* @return the player's position
*/
Vector3f position();
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2025 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.event.java.ServerCodeOfConductEvent;
/**
* Fired when a player accepts a code of conduct sent by the Java server. API users can listen to this event
* to store the acceptance in a cache, and tell Geyser not to do so.
*
* <p>Java clients cache acceptance locally, but bedrock clients don't. Normally Geyser uses a simple JSON file to implement this,
* but an alternative solution may be preferred when using multiple Geyser instances. Such a solution can be implemented through this event and {@link ServerCodeOfConductEvent}.</p>
*
* @see ServerCodeOfConductEvent
* @since 2.9.0
*/
public class SessionAcceptCodeOfConductEvent extends ConnectionEvent {
private final String codeOfConduct;
private boolean skipSaving = false;
public SessionAcceptCodeOfConductEvent(@NonNull GeyserConnection connection, String codeOfConduct) {
super(connection);
this.codeOfConduct = codeOfConduct;
}
/**
* @return the code of conduct sent by the server
* @since 2.9.0
*/
public String codeOfConduct() {
return codeOfConduct;
}
/**
* @return {@code true} if Geyser should not save the acceptance of the code of conduct in its own cache (through a JSON file), because it was saved elsewhere
* @since 2.9.0
*/
public boolean shouldSkipSaving() {
return skipSaving;
}
/**
* Sets {@link SessionAcceptCodeOfConductEvent#shouldSkipSaving()} to {@code true}.
* @since 2.9.0
*/
public void skipSaving() {
this.skipSaving = true;
}
}

View File

@@ -50,7 +50,7 @@ public class SessionDisconnectEvent extends ConnectionEvent {
}
/**
* Sets the disconnect reason, thereby overriding th original reason.
* Sets the disconnect message shown to the Bedrock client.
*
* @param disconnectReason the reason for the disconnect
*/

View File

@@ -31,6 +31,7 @@ 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.
* @since 2.1.1
*/
public final class SessionJoinEvent extends ConnectionEvent {
public SessionJoinEvent(@NonNull GeyserConnection connection) {

View File

@@ -26,15 +26,20 @@
package org.geysermc.geyser.api.event.bedrock;
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.event.connection.ConnectionEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.exception.ResourcePackException;
import org.geysermc.geyser.api.pack.option.ResourcePackOption;
import java.util.Collection;
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.
* Called when Geyser initializes a session for a new Bedrock client and is in the process of sending {@link ResourcePack}'s.
* @since 2.1.1
*/
public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent {
public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) {
@@ -42,26 +47,80 @@ public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent {
}
/**
* Gets an unmodifiable list of {@link ResourcePack}s that will be sent to the client.
* Gets the {@link ResourcePack}'s that will be sent to this {@link GeyserConnection}.
* To remove packs, use {@link #unregister(UUID)}, as the list returned
* by this method is unmodifiable.
*
* @return an unmodifiable list of resource packs that will be sent to the client.
* @return an unmodifiable list of {@link ResourcePack}'s
* @since 2.1.1
*/
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
* @deprecated Use {{@link #register(ResourcePack, ResourcePackOption[])}} instead
*/
public abstract boolean register(@NonNull ResourcePack resourcePack);
@Deprecated
public abstract boolean register(@NonNull ResourcePack pack);
/**
* Unregisters a resource pack from being sent to the client.
* Registers a {@link ResourcePack} to be sent to the client, optionally alongside
* specific {@link ResourcePackOption}'s specifying how it will be applied by the client.
*
* @param uuid the UUID of the resource pack
* @return true whether the resource pack was removed from the list of resource packs.
* @param pack the {@link ResourcePack} that will be sent to the client
* @param options {@link ResourcePackOption}'s that specify how the client loads the pack
* @throws ResourcePackException if an issue occurred during pack registration
* @since 2.6.2
*/
public abstract void register(@NonNull ResourcePack pack, @Nullable ResourcePackOption<?>... options);
/**
* Sets {@link ResourcePackOption}'s for a {@link ResourcePack}.
* This method can also be used to override options for resource packs already registered in the
* {@link org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent}.
*
* @param uuid the uuid of the resource pack to register the options for
* @param options the {@link ResourcePackOption}'s to register for the resource pack
* @throws ResourcePackException if an issue occurred during {@link ResourcePackOption} registration
* @since 2.6.2
*/
public abstract void registerOptions(@NonNull UUID uuid, @NonNull ResourcePackOption<?>... options);
/**
* Returns a collection of {@link ResourcePackOption}'s for a registered {@link ResourcePack}.
* The collection returned here is not modifiable.
*
* @param uuid the {@link ResourcePack} for which the options are set
* @return a collection of {@link ResourcePackOption}'s
* @throws ResourcePackException if the pack was not registered
* @since 2.6.2
*/
public abstract Collection<ResourcePackOption<?>> options(@NonNull UUID uuid);
/**
* Returns the current {@link ResourcePackOption}, or null, for a given {@link ResourcePackOption.Type}.
*
* @param uuid the {@link ResourcePack} for which to query this option type
* @param type the {@link ResourcePackOption.Type} of the option to query
* @throws ResourcePackException if the queried option is invalid or not present on the resource pack
* @since 2.6.2
*/
public abstract @Nullable ResourcePackOption<?> option(@NonNull UUID uuid, ResourcePackOption.@NonNull Type type);
/**
* Unregisters a {@link ResourcePack} from the list of packs sent to this {@link GeyserConnection}.
*
* @param uuid the UUID of the {@link ResourcePack} to be removed
* @since 2.1.1
*/
public abstract boolean unregister(@NonNull UUID uuid);
/**
* Whether to forcefully disable vibrant visuals for joining clients.
* While vibrant visuals are nice to look at, they can cause issues with
* some resource packs.
*
* @param enabled Whether vibrant visuals are allowed. This is true by default.
* @since 2.7.2
*/
public abstract void allowVibrantVisuals(boolean enabled);
}

View File

@@ -31,19 +31,29 @@ 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;
import org.geysermc.geyser.api.util.PlatformType;
import java.util.Map;
import java.util.Objects;
/**
* Called when a session has logged in, and is about to connect to a remote java server.
* 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;
private Map<String, byte[]> cookies;
private boolean transferring;
public SessionLoginEvent(@NonNull GeyserConnection connection, @NonNull RemoteServer remoteServer) {
public SessionLoginEvent(@NonNull GeyserConnection connection,
@NonNull RemoteServer remoteServer,
@NonNull Map<String, byte[]> cookies) {
super(connection);
this.remoteServer = remoteServer;
this.cookies = cookies;
this.transferring = false;
}
/**
@@ -90,9 +100,9 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella
}
/**
* Gets the {@link RemoteServer} the section will attempt to connect to.
* Gets the {@link RemoteServer} the session will attempt to connect to.
*
* @return the {@link RemoteServer} the section will attempt to connect to.
* @return the {@link RemoteServer} the session will attempt to connect to.
*/
public @NonNull RemoteServer remoteServer() {
return this.remoteServer;
@@ -100,10 +110,44 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella
/**
* Sets the {@link RemoteServer} to connect the session to.
* This method will only work as expected on {@link PlatformType#STANDALONE},
* as on other Geyser platforms, the remote server is not determined by Geyser.
*
* @param remoteServer Sets the {@link RemoteServer} to connect to.
*/
public void remoteServer(@NonNull RemoteServer remoteServer) {
this.remoteServer = remoteServer;
}
/**
* Sets a map of cookies from a possible previous session. The Java server can send and request these
* to store information on the client across server transfers.
*/
public void cookies(@NonNull Map<String, byte[]> cookies) {
Objects.requireNonNull(cookies);
this.cookies = cookies;
}
/**
* Gets a map of the sessions cookies, if set.
* @return the connections cookies
*/
public @NonNull Map<String, byte[]> cookies() {
return cookies;
}
/**
* Determines the connection intent of the connection
*/
public void transferring(boolean transferring) {
this.transferring = transferring;
}
/**
* Gets whether this login attempt to the Java server
* has the transfer intent
*/
public boolean transferring() {
return this.transferring;
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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.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.skin.Cape;
import org.geysermc.geyser.api.skin.Skin;
import org.geysermc.geyser.api.skin.SkinData;
import org.geysermc.geyser.api.skin.SkinGeometry;
import java.util.UUID;
/**
* Called when a skin is applied to a player.
* <p>
* Won't be called when a fake player is spawned for a player skull.
*/
public abstract class SessionSkinApplyEvent extends ConnectionEvent {
private final String username;
private final UUID uuid;
private final boolean slim;
private final boolean bedrock;
private final SkinData originalSkinData;
public SessionSkinApplyEvent(@NonNull GeyserConnection connection, String username, UUID uuid, boolean slim, boolean bedrock, SkinData skinData) {
super(connection);
this.username = username;
this.uuid = uuid;
this.slim = slim;
this.bedrock = bedrock;
this.originalSkinData = skinData;
}
/**
* The username of the player.
*
* @return the username of the player
*/
public @NonNull String username() {
return username;
}
/**
* The UUID of the player.
*
* @return the UUID of the player
*/
public @NonNull UUID uuid() {
return uuid;
}
/**
* If the player is using a slim model.
*
* @return if the player is using a slim model
*/
public boolean slim() {
return slim;
}
/**
* If the player is a Bedrock player.
*
* @return if the player is a Bedrock player
*/
public boolean bedrock() {
return bedrock;
}
/**
* The original skin data of the player.
*
* @return the original skin data of the player
*/
public @NonNull SkinData originalSkin() {
return originalSkinData;
}
/**
* The skin data of the player.
*
* @return the current skin data of the player
*/
public abstract @NonNull SkinData skinData();
/**
* Change the skin of the player.
*
* @param newSkin the new skin
*/
public abstract void skin(@NonNull Skin newSkin);
/**
* Change the cape of the player.
*
* @param newCape the new cape
*/
public abstract void cape(@NonNull Cape newCape);
/**
* Change the geometry of the player.
*
* @param newGeometry the new geometry
*/
public abstract void geometry(@NonNull SkinGeometry newGeometry);
/**
* Change the geometry of the player.
* <p>
* Constructs a generic {@link SkinGeometry} object with the given data.
*
* @param geometryName the name of the geometry
* @param geometryData the data of the geometry
*/
public void geometry(@NonNull String geometryName, @NonNull String geometryData) {
geometry(new SkinGeometry("{\"geometry\" :{\"default\" :\"" + geometryName + "\"}}", geometryData));
}
}

View File

@@ -0,0 +1,110 @@
/*
* 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.connection;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.event.Cancellable;
import org.geysermc.event.Event;
import java.net.InetSocketAddress;
/**
* Called whenever a client attempts to connect to the server, before the connection is accepted.
*/
public final class ConnectionRequestEvent implements Event, Cancellable {
private boolean cancelled;
private final InetSocketAddress ip;
private final InetSocketAddress proxyIp;
public ConnectionRequestEvent(@NonNull InetSocketAddress ip, @Nullable InetSocketAddress proxyIp) {
this.ip = ip;
this.proxyIp = proxyIp;
}
/**
* The IP address of the client attempting to connect
*
* @return the IP address of the client attempting to connect
* @deprecated Use {@link #inetSocketAddress()} instead
*/
@NonNull @Deprecated(forRemoval = true)
public InetSocketAddress getInetSocketAddress() {
return ip;
}
/**
* The IP address of the proxy handling the connection. It will return null if there is no proxy.
*
* @return the IP address of the proxy handling the connection
* @deprecated Use {@link #proxyIp()} instead
*/
@Nullable @Deprecated(forRemoval = true)
public InetSocketAddress getProxyIp() {
return proxyIp;
}
/**
* The IP address of the client attempting to connect
*
* @return the IP address of the client attempting to connect
*/
@NonNull
public InetSocketAddress inetSocketAddress() {
return ip;
}
/**
* The IP address of the proxy handling the connection. It will return null if there is no proxy.
*
* @return the IP address of the proxy handling the connection
*/
@Nullable
public InetSocketAddress proxyIp() {
return proxyIp;
}
/**
* The cancel status of this event. If this event is cancelled, the connection will be rejected.
*
* @return the cancel status of this event
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* Sets the cancel status of this event. If this event is canceled, the connection will be rejected.
*
* @param cancelled the cancel status of this event.
*/
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@@ -33,10 +33,10 @@ import org.geysermc.event.Event;
import java.net.InetSocketAddress;
/**
* Called whenever Geyser gets pinged
* Called whenever Geyser gets pinged by a Bedrock client.
* <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.
* 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 the information provided in this event.
*/
public interface GeyserBedrockPingEvent extends Event {

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2025 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.java;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.bedrock.SessionAcceptCodeOfConductEvent;
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
/**
* Fired when the Java server sends a code of conduct during the configuration phase.
* API users can listen to this event and tell Geyser the player has accepted the code of conduct before, which will result in the
* code of conduct not being shown to the player.
*
* <p>Java clients cache this locally, but bedrock clients don't. Normally Geyser uses a simple JSON file to implement this,
* but an alternative solution may be preferred when using multiple Geyser instances. Such a solution can be implemented through this event and {@link SessionAcceptCodeOfConductEvent}.</p>
*
* @see SessionAcceptCodeOfConductEvent
* @since 2.9.0
*/
public final class ServerCodeOfConductEvent extends ConnectionEvent {
private final String codeOfConduct;
private boolean hasAccepted = false;
public ServerCodeOfConductEvent(@NonNull GeyserConnection connection, String codeOfConduct) {
super(connection);
this.codeOfConduct = codeOfConduct;
}
/**
* @return the code of conduct sent by the server
* @since 2.9.0
*/
public String codeOfConduct() {
return codeOfConduct;
}
/**
* @return {@code true} if Geyser should not show the code of conduct to the player, because they have already accepted it
* @since 2.9.0
*/
public boolean accepted() {
return hasAccepted;
}
/**
* Sets {@link ServerCodeOfConductEvent#accepted()} to {@code true}.
* @since 2.9.0
*/
public void accept() {
this.hasAccepted = true;
}
}

View File

@@ -37,7 +37,7 @@ import java.util.Set;
* <br>
* This event is mapped to the existence of Brigadier on the server.
*/
public class ServerDefineCommandsEvent extends ConnectionEvent implements Cancellable {
public final class ServerDefineCommandsEvent extends ConnectionEvent implements Cancellable {
private final Set<? extends CommandInfo> commands;
private boolean cancelled;

View File

@@ -0,0 +1,125 @@
/*
* 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.java;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.value.qual.IntRange;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
import java.util.Map;
/**
* Fired when the Java server sends a transfer request to a different Java server.
* Geyser Extensions can listen to this event and set a target server ip/port for Bedrock players to be transferred to.
*/
public final class ServerTransferEvent extends ConnectionEvent {
private final String host;
private final int port;
private String bedrockHost;
private int bedrockPort;
private final Map<String, byte[]> cookies;
public ServerTransferEvent(@NonNull GeyserConnection connection,
@NonNull String host, int port, @NonNull Map<String, byte[]> cookies) {
super(connection);
this.host = host;
this.port = port;
this.cookies = cookies;
this.bedrockHost = null;
this.bedrockPort = -1;
}
/**
* The host that the Java server requests a transfer to.
*
* @return the host
*/
public @NonNull String host() {
return this.host;
}
/**
* The port that the Java server requests a transfer to.
*
* @return the port
*/
public int port() {
return this.port;
}
/**
* The host that the Bedrock player should try and connect to.
* If this is not set, the Bedrock player will just be disconnected.
*
* @return the host where the Bedrock client will be transferred to, or null if not set.
*/
public @Nullable String bedrockHost() {
return this.bedrockHost;
}
/**
* The port that the Bedrock player should try and connect to.
* If this is not set, the Bedrock player will just be disconnected.
*
* @return the port where the Bedrock client will be transferred to, or -1 if not set.
*/
public int bedrockPort() {
return this.bedrockPort;
}
/**
* Sets the host for the Bedrock player to be transferred to
*/
public void bedrockHost(@NonNull String host) {
if (host == null || host.isBlank()) {
throw new IllegalArgumentException("Server address cannot be null or blank");
}
this.bedrockHost = host;
}
/**
* Sets the port for the Bedrock player to be transferred to
*/
public void bedrockPort(@IntRange(from = 0, to = 65535) int port) {
if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Server port must be between 0 and 65535, was " + port);
}
this.bedrockPort = port;
}
/**
* Gets a map of the sessions current cookies.
*
* @return the connections cookies
*/
public @NonNull Map<String, byte[]> cookies() {
return cookies;
}
}

View File

@@ -50,7 +50,7 @@ public interface GeyserDefineCommandsEvent extends Event {
/**
* Gets all the registered built-in {@link Command}s.
*
* @return all the registered built-in commands
* @return all the registered built-in commands as an unmodifiable map
*/
@NonNull
Map<String, Command> commands();

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 2025 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.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.event.Event;
import org.geysermc.geyser.api.entity.EntityData;
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
import org.geysermc.geyser.api.entity.property.type.GeyserBooleanEntityProperty;
import org.geysermc.geyser.api.entity.property.type.GeyserEnumEntityProperty;
import org.geysermc.geyser.api.entity.property.type.GeyserFloatEntityProperty;
import org.geysermc.geyser.api.entity.property.type.GeyserIntEntityProperty;
import org.geysermc.geyser.api.entity.property.type.GeyserStringEnumProperty;
import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.api.util.Identifier;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
/**
* Lifecycle event fired during Geyser's startup to allow custom entity properties
* to be registered for a specific entity type.
* <p>
* Listeners can add new properties for any entity by passing the target entity's
* identifier (e.g., {@code Identifier.of("player")}) to the registration methods.
* The returned {@link GeyserEntityProperty} is used to identify the properties and to
* update the value of a specific entity instance.
*
* <h2>Example usage</h2>
* <pre>{@code
* public void onDefine(GeyserDefineEntityPropertiesEvent event) {
* Identifier player = Identifier.of("player");
* GeyserFloatEntityProperty ANIMATION_SPEED =
* event.registerFloatProperty(player, Identifier.of("my_group:animation_speed"), 0.0f, 1.0f, 0.1f);
* GeyserBooleanEntityProperty SHOW_SHORTS =
* event.registerBooleanProperty(player, Identifier.of("my_group:show_shorts"), false);
* }
* }</pre>
*
* Retrieving entity instances is possible with the {@link EntityData#entityByJavaId(int)} method, or
* {@link EntityData#playerEntity()} for the connection player entity.
* To update the value of a property on a specific entity, use {@link GeyserEntity#updateProperty(GeyserEntityProperty, Object)},
* or {@link GeyserEntity#updatePropertiesBatched(Consumer)} to update multiple properties efficiently at once.
*
* <p><b>Notes:</b>
* <ul>
* <li>Default values must fall within the provided bounds.</li>
* <li>There cannot be more than 32 properties registered per entity type in total</li>
* <li>{@link #properties(Identifier)} returns properties registered for the given entity
* (including those added earlier in the same callback), including vanilla properties.</li>
* </ul>
*
* @since 2.9.0
*/
public interface GeyserDefineEntityPropertiesEvent extends Event {
/**
* Returns an <em>unmodifiable</em> view of all properties that have been registered
* so far for the given entity type. This includes entity properties used for vanilla gameplay,
* such as those used for creaking animations.
*
* @param entityType the Java edition entity type identifier
* @return an unmodifiable collection of registered properties
*
* @since 2.9.0
*/
Collection<GeyserEntityProperty<?>> properties(@NonNull Identifier entityType);
/**
* Registers a {@code float}-backed entity property.
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param min the minimum allowed value (inclusive)
* @param max the maximum allowed value (inclusive)
* @param defaultValue the default value assigned initially on entity spawn - if null, it will be the minimum value
* @return the created float property
*
* @since 2.9.0
*/
GeyserFloatEntityProperty registerFloatProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, float min, float max, @Nullable Float defaultValue);
/**
* Registers a {@code float}-backed entity property with a default value set to the minimum value.
* @see #registerFloatProperty(Identifier, Identifier, float, float, Float)
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param min the minimum allowed value (inclusive)
* @param max the maximum allowed value (inclusive)
* @return the created float property
*
* @since 2.9.0
*/
default GeyserFloatEntityProperty registerFloatProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, float min, float max) {
return registerFloatProperty(entityType, propertyIdentifier, min, max, null);
}
/**
* Registers an {@code int}-backed entity property.
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param min the minimum allowed value (inclusive)
* @param max the maximum allowed value (inclusive)
* @param defaultValue the default value assigned initially on entity spawn - if null, it will be the minimum value
* @return the created int property
*
* @since 2.9.0
*/
GeyserIntEntityProperty registerIntegerProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, int min, int max, @Nullable Integer defaultValue);
/**
* Registers an {@code int}-backed entity property with a default value set to the minimum value.
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param min the minimum allowed value (inclusive)
* @param max the maximum allowed value (inclusive)
* @return the created int property
*
* @since 2.9.0
*/
default GeyserIntEntityProperty registerIntegerProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, int min, int max) {
return registerIntegerProperty(entityType, propertyIdentifier, min, max, null);
}
/**
* Registers a {@code boolean}-backed entity property.
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param defaultValue the default boolean value
* @return the created boolean property handle
*
* @since 2.9.0
*/
GeyserBooleanEntityProperty registerBooleanProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, boolean defaultValue);
/**
* Registers a {@code boolean}-backed entity property with a default of {@code false}.
* @see #registerBooleanProperty(Identifier, Identifier, boolean)
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @return the created boolean property
* @since 2.9.0
*/
default GeyserBooleanEntityProperty registerBooleanProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier) {
return registerBooleanProperty(entityType, propertyIdentifier, false);
}
/**
* Registers a typed {@linkplain Enum enum}-backed entity property.
* <p>
* The enum constants define the allowed values. If {@code defaultValue} is {@code null},
* the first enum value is set as the default.
* @see GeyserEnumEntityProperty for further limitations
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param enumClass the enum class that defines allowed values
* @param defaultValue the default enum value, or {@code null} for the first enum value to be the default
* @param <E> the enum type
* @return the created enum property
*
* @since 2.9.0
*/
<E extends Enum<E>> GeyserEnumEntityProperty<E> registerEnumProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, @NonNull Class<E> enumClass, @Nullable E defaultValue);
/**
* Registers a typed {@linkplain Enum enum}-backed entity property with the first value set as the default.
* @see #registerEnumProperty(Identifier, Identifier, Class, Enum)
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param enumClass the enum class that defines allowed values
* @param <E> the enum type
* @return the created enum property
*
* @since 2.9.0
*/
default <E extends Enum<E>> GeyserEnumEntityProperty<E> registerEnumProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, @NonNull Class<E> enumClass) {
return registerEnumProperty(entityType, propertyIdentifier, enumClass, null);
}
/**
* Registers a string-backed "enum-like" entity property where the set of allowed values
* is defined by the provided list. If {@code defaultValue} is {@code null}, the first value is used as the default
* on entity spawn. The default must be one of the values in {@code values}.
* @see GeyserStringEnumProperty
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param values the allowed string values
* @param defaultValue the default string value, or {@code null} for the first value to be used
* @return the created string-enum property
*
* @since 2.9.0
*/
GeyserStringEnumProperty registerEnumProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, @NonNull List<String> values, @Nullable String defaultValue);
/**
* Registers a string-backed "enum-like" entity property with the first value as the default.
* @see #registerEnumProperty(Identifier, Identifier, List, String)
*
* @param entityType the Java edition entity type identifier
* @param propertyIdentifier the unique property identifier
* @param values the allowed string values
* @return the created string-enum property handle
*
* @since 2.9.0
*/
default GeyserStringEnumProperty registerEnumProperty(@NonNull Identifier entityType, @NonNull Identifier propertyIdentifier, @NonNull List<String> values) {
return registerEnumProperty(entityType, propertyIdentifier, values, null);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2019-2025 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.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.event.Event;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.exception.ResourcePackException;
import org.geysermc.geyser.api.pack.option.ResourcePackOption;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
* Called when {@link ResourcePack}'s are loaded within Geyser.
* @since 2.6.2
*/
public abstract class GeyserDefineResourcePacksEvent implements Event {
/**
* Gets the {@link ResourcePack}'s that will be sent to connecting Bedrock clients.
* To remove packs, use {@link #unregister(UUID)}, as the list returned
* by this method is unmodifiable.
*
* @return an unmodifiable list of {@link ResourcePack}'s
* @since 2.6.2
*/
public abstract @NonNull List<ResourcePack> resourcePacks();
/**
* Registers a {@link ResourcePack} to be sent to the client, optionally alongside
* {@link ResourcePackOption}'s specifying how it will be applied on clients.
*
* @param pack a resource pack that will be sent to the client
* @param options {@link ResourcePackOption}'s that specify how clients load the pack
* @throws ResourcePackException if an issue occurred during pack registration
* @since 2.6.2
*/
public abstract void register(@NonNull ResourcePack pack, @Nullable ResourcePackOption<?>... options);
/**
* Sets {@link ResourcePackOption}'s for a {@link ResourcePack}.
*
* @param uuid the uuid of the resource pack to register the options for
* @param options the {@link ResourcePackOption}'s to register for the resource pack
* @throws ResourcePackException if an issue occurred during {@link ResourcePackOption} registration
* @since 2.6.2
*/
public abstract void registerOptions(@NonNull UUID uuid, @NonNull ResourcePackOption<?>... options);
/**
* Returns a collection of {@link ResourcePackOption}'s for a registered {@link ResourcePack}.
* The collection returned here is not modifiable.
*
* @param uuid the uuid of the {@link ResourcePack} for which the options are set
* @return a collection of {@link ResourcePackOption}'s
* @throws ResourcePackException if the pack was not registered
* @since 2.6.2
*/
public abstract Collection<ResourcePackOption<?>> options(@NonNull UUID uuid);
/**
* Returns the current option, or null, for a given {@link ResourcePackOption.Type}.
*
* @param uuid the {@link ResourcePack} for which to query this option type
* @param type the {@link ResourcePackOption.Type} of the option to query
* @throws ResourcePackException if the queried option is invalid or not present on the resource pack
* @since 2.6.2
*/
public abstract @Nullable ResourcePackOption<?> option(@NonNull UUID uuid, ResourcePackOption.@NonNull Type type);
/**
* Unregisters a {@link ResourcePack} from the list of packs sent to connecting Bedrock clients.
*
* @param uuid the UUID of the {@link ResourcePack} to be removed
* @since 2.6.2
*/
public abstract void unregister(@NonNull UUID uuid);
}

View File

@@ -32,9 +32,8 @@ import java.nio.file.Path;
import java.util.List;
/**
* Called when resource packs are loaded within Geyser.
*
* @param resourcePacks a mutable list of the currently listed resource packs
* @deprecated Use the {@link GeyserDefineResourcePacksEvent} instead.
*/
@Deprecated
public record GeyserLoadResourcePacksEvent(@NonNull List<Path> resourcePacks) implements Event {
}

View File

@@ -33,7 +33,7 @@ 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}.
* After this event is fired, some lifecycle events can be fired again - such as the {@link GeyserDefineResourcePacksEvent}.
*
* @param extensionManager the extension manager
* @param eventBus the event bus

View File

@@ -0,0 +1,42 @@
/*
* 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.lifecycle;
import org.geysermc.event.Event;
import org.geysermc.event.PostOrder;
import org.geysermc.geyser.api.permission.PermissionChecker;
/**
* Fired by any permission manager implementations that wish to add support for custom permission checking.
* This event is not guaranteed to be fired - it is currently only fired on Geyser-Standalone and ViaProxy.
* <p>
* Subscribing to this event with an earlier {@link PostOrder} and registering a {@link PermissionChecker}
* will result in that checker having a higher priority than others.
*/
public interface GeyserRegisterPermissionCheckersEvent extends Event {
void register(PermissionChecker checker);
}

View File

@@ -0,0 +1,51 @@
/*
* 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.lifecycle;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.event.Event;
import org.geysermc.geyser.api.util.TriState;
/**
* Fired by anything that wishes to gather permission nodes and defaults.
* <p>
* This event is not guaranteed to be fired, as certain Geyser platforms do not have a native permission system.
* It can be expected to fire on Geyser-Spigot, Geyser-NeoForge, Geyser-Standalone, and Geyser-ViaProxy
* It may be fired by a 3rd party regardless of the platform.
*/
public interface GeyserRegisterPermissionsEvent extends Event {
/**
* Registers a permission node and its default value with the firer.<p>
* {@link TriState#TRUE} corresponds to all players having the permission by default.<br>
* {@link TriState#NOT_SET} corresponds to only server operators having the permission by default (if such a concept exists on the platform).<br>
* {@link TriState#FALSE} corresponds to no players having the permission by default.<br>
*
* @param permission the permission node to register
* @param defaultValue the default value of the node
*/
void register(@NonNull String permission, @NonNull TriState defaultValue);
}

View File

@@ -107,6 +107,15 @@ public interface Extension extends EventRegistrar {
return this.extensionLoader().description(this);
}
/**
* @return the root command that all of this extension's commands will stem from.
* By default, this is the extension's id.
*/
@NonNull
default String rootCommand() {
return this.description().id();
}
/**
* Gets the extension's logger
*

View File

@@ -59,33 +59,46 @@ public interface ExtensionDescription {
String main();
/**
* Gets the extension's major api version
* Represents the human api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's major api version
* @return the extension's requested human api version
*/
int humanApiVersion();
/**
* Represents the major api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's requested major api version
*/
int majorApiVersion();
/**
* Gets the extension's minor api version
* Represents the minor api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's minor api version
* @return the extension's requested minor api version
*/
int minorApiVersion();
/**
* Gets the extension's patch api version
*
* @return the extension's patch api version
* No longer in use. Geyser is now using an adaption of the romantic versioning scheme.
* See <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">here</a> for details.
*/
int patchApiVersion();
@Deprecated(forRemoval = true)
default int patchApiVersion() {
return minorApiVersion();
}
/**
* Gets the extension's api version.
*
* @return the extension's api version
* Returns the extension's requested Geyser Api version.
*/
default String apiVersion() {
return majorApiVersion() + "." + minorApiVersion() + "." + patchApiVersion();
return humanApiVersion() + "." + majorApiVersion() + "." + minorApiVersion();
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
* 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
@@ -80,10 +80,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String toolType();
/**
* Gets the tool tier of the item.
*
* @return the tool tier of the item
* @deprecated no longer used
*/
@Deprecated(forRemoval = true)
@Nullable String toolTier();
/**
@@ -108,10 +107,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String translationString();
/**
* Gets the repair materials of the item.
*
* @return the repair materials of the item
* @deprecated No longer used.
*/
@Deprecated(forRemoval = true)
@Nullable Set<String> repairMaterials();
/**
@@ -161,6 +159,13 @@ public interface NonVanillaCustomItemData extends CustomItemData {
return displayHandheld();
}
/**
* Gets the block the item places.
*
* @return the block the item places
*/
String block();
static NonVanillaCustomItemData.Builder builder() {
return GeyserApi.api().provider(NonVanillaCustomItemData.Builder.class);
}
@@ -201,6 +206,8 @@ public interface NonVanillaCustomItemData extends CustomItemData {
Builder chargeable(boolean isChargeable);
Builder block(String block);
/**
* @deprecated Use {@link #displayHandheld(boolean)} instead.
*/

View File

@@ -35,6 +35,7 @@ import java.nio.file.Path;
/**
* Represents a pack codec that can be used
* to provide resource packs to clients.
* @since 2.1.1
*/
public abstract class PackCodec {
@@ -42,6 +43,7 @@ public abstract class PackCodec {
* Gets the sha256 hash of the resource pack.
*
* @return the hash of the resource pack
* @since 2.1.1
*/
public abstract byte @NonNull [] sha256();
@@ -49,34 +51,66 @@ public abstract class PackCodec {
* Gets the resource pack size.
*
* @return the resource pack file size
* @since 2.1.1
*/
public abstract long size();
/**
* Serializes the given resource pack into a byte buffer.
* @deprecated use {@link #serialize()} instead.
*/
@Deprecated
@NonNull
public SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException {
return serialize();
};
/**
* Serializes the given codec into a byte buffer.
*
* @param resourcePack the resource pack to serialize
* @return the serialized resource pack
* @since 2.6.2
*/
@NonNull
public abstract SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException;
public abstract SeekableByteChannel serialize() throws IOException;
/**
* Creates a new resource pack from this codec.
*
* @return the new resource pack
* @since 2.1.1
*/
@NonNull
protected abstract ResourcePack create();
/**
* Creates a new resource pack builder from this codec.
*
* @return the new resource pack builder
* @since 2.6.2
*/
protected abstract ResourcePack.@NonNull Builder createBuilder();
/**
* Creates a new pack provider from the given path.
*
* @param path the path to create the pack provider from
* @return the new pack provider
* @since 2.1.1
*/
@NonNull
public static PackCodec path(@NonNull Path path) {
return GeyserApi.api().provider(PathPackCodec.class, path);
}
/**
* Creates a new pack provider from the given url.
*
* @param url the url to create the pack provider from
* @return the new pack provider
* @since 2.6.2
*/
@NonNull
public static PackCodec url(@NonNull String url) {
return GeyserApi.api().provider(UrlPackCodec.class, url);
}
}

View File

@@ -32,6 +32,7 @@ import java.nio.file.Path;
/**
* Represents a pack codec that creates a resource
* pack from a path on the filesystem.
* @since 2.1.1
*/
public abstract class PathPackCodec extends PackCodec {
@@ -39,7 +40,8 @@ public abstract class PathPackCodec extends PackCodec {
* Gets the path of the resource pack.
*
* @return the path of the resource pack
* @since 2.1.1
*/
@NonNull
public abstract Path path();
}
}

View File

@@ -26,12 +26,16 @@
package org.geysermc.geyser.api.pack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.common.returnsreceiver.qual.This;
import java.util.UUID;
/**
* 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.
* @since 2.1.1
*/
public interface ResourcePack {
@@ -39,6 +43,7 @@ public interface ResourcePack {
* The {@link PackCodec codec} for this pack.
*
* @return the codec for this pack
* @since 2.1.1
*/
@NonNull
PackCodec codec();
@@ -47,6 +52,7 @@ public interface ResourcePack {
* Gets the resource pack manifest.
*
* @return the resource pack manifest
* @since 2.1.1
*/
@NonNull
ResourcePackManifest manifest();
@@ -55,18 +61,83 @@ public interface ResourcePack {
* 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
* @since 2.1.1
*/
@NonNull
String contentKey();
/**
* Shortcut for getting the UUID from the {@link ResourcePackManifest}.
*
* @return the resource pack uuid
* @since 2.6.2
*/
@NonNull
default UUID uuid() {
return manifest().header().uuid();
}
/**
* Creates a resource pack with the given {@link PackCodec}.
*
* @param codec the pack codec
* @return the resource pack
* @since 2.1.1
*/
@NonNull
static ResourcePack create(@NonNull PackCodec codec) {
return codec.create();
}
/**
* Returns a {@link Builder} for a resource pack.
* It can be used to set a content key.
*
* @param codec the {@link PackCodec} to base the builder on
* @return a {@link Builder} to build a resource pack
* @since 2.6.2
*/
static Builder builder(@NonNull PackCodec codec) {
return codec.createBuilder();
}
/**
* A builder for a resource pack. It allows providing a content key manually.
* @since 2.6.2
*/
interface Builder {
/**
* @return the {@link ResourcePackManifest} of this resource pack
* @since 2.6.2
*/
ResourcePackManifest manifest();
/**
* @return the {@link PackCodec} of this resource pack
* @since 2.6.2
*/
PackCodec codec();
/**
* @return the current content key, or an empty string if not set
* @since 2.6.2
*/
String contentKey();
/**
* Sets a content key for this resource pack.
*
* @param contentKey the content key
* @return this builder
* @since 2.6.2
*/
@This Builder contentKey(@NonNull String contentKey);
/**
* @return the resource pack
* @since 2.6.2
*/
ResourcePack build();
}
}

View File

@@ -26,55 +26,99 @@
package org.geysermc.geyser.api.pack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent;
import org.geysermc.geyser.api.pack.option.SubpackOption;
import java.util.Collection;
import java.util.UUID;
/**
* Represents a resource pack manifest.
* Represents a Bedrock edition resource pack manifest (manifest.json).
* All resource packs are required to have such a file as it identifies the resource pack.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/reference/content/addonsreference/examples/addonmanifest?view=minecraft-bedrock-stable">
* Microsoft's docs for more info</a>.
* @since 2.1.1
*/
public interface ResourcePackManifest {
/**
* Gets the format version of the resource pack.
* <p>
* "1" is used for skin packs,
* "2" is used for resource and behavior packs, and world templates.
*
* @return the format version
* @since 2.1.1
*/
int formatVersion();
/**
* Gets the header of the resource pack.
* Gets the {@link Header} of the resource pack.
*
* @return the header
* @return the {@link Header}
* @since 2.1.1
*/
@NonNull
Header header();
/**
* Gets the modules of the resource pack.
* Gets the {@link Module}'s of the resource pack.
*
* @return the modules
* @return a collection of modules
* @since 2.1.1
*/
@NonNull
Collection<? extends Module> modules();
/**
* Gets the dependencies of the resource pack.
* Gets the {@link Dependency}'s of the resource pack.
*
* @return the dependencies
* @return a collection of dependencies
* @since 2.6.2
*/
@NonNull
Collection<? extends Dependency> dependencies();
/**
* Gets the {@link Subpack}'s of the resource pack.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/documents/utilizingsubpacks">Microsoft's docs on subpacks
* </a> for more information.
*
* @return a collection of subpacks
* @since 2.6.2
*/
@NonNull
Collection<? extends Subpack> subpacks();
/**
* Gets the {@link Setting}'s of the resource pack.
* These are shown to Bedrock client's in the resource pack settings menu (<a href="https://learn.microsoft.com/en-us/minecraft/creator/documents/media/utilizingsubpacks/subpackgif.gif?view=minecraft-bedrock-stable">see here</a>)
* to inform users about what the resource pack and sub-packs include.
*
* @return a collection of settings
* @since 2.6.2
*/
@NonNull
Collection<? extends Setting> settings();
/**
* Represents the header of a resource pack.
* It contains the main information about the resource pack, such as
* the name, description, or uuid.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/reference/content/addonsreference/examples/addonmanifest?view=minecraft-bedrock-stable#header">
* Microsoft's docs for further details on headers.</a>
* @since 2.1.1
*/
interface Header {
/**
* Gets the UUID of the resource pack.
* Gets the UUID of the resource pack. It is a unique identifier that differentiates this resource pack from any other resource pack.
* Bedrock clients will cache resource packs, and download resource packs when the uuid is new (or the version changes).
*
* @return the UUID
* @since 2.1.1
*/
@NonNull
UUID uuid();
@@ -83,6 +127,7 @@ public interface ResourcePackManifest {
* Gets the version of the resource pack.
*
* @return the version
* @since 2.1.1
*/
@NonNull
Version version();
@@ -91,6 +136,7 @@ public interface ResourcePackManifest {
* Gets the name of the resource pack.
*
* @return the name
* @since 2.1.1
*/
@NonNull
String name();
@@ -99,6 +145,7 @@ public interface ResourcePackManifest {
* Gets the description of the resource pack.
*
* @return the description
* @since 2.1.1
*/
@NonNull
String description();
@@ -107,6 +154,7 @@ public interface ResourcePackManifest {
* Gets the minimum supported Minecraft version of the resource pack.
*
* @return the minimum supported Minecraft version
* @since 2.1.1
*/
@NonNull
Version minimumSupportedMinecraftVersion();
@@ -114,21 +162,29 @@ public interface ResourcePackManifest {
/**
* Represents a module of a resource pack.
* It contains information about the content type that is
* offered by this resource pack.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/reference/content/addonsreference/examples/addonmanifest?view=minecraft-bedrock-stable#modules">
* Microsoft's docs for further details on modules.</a>
* @since 2.1.1
*/
interface Module {
/**
* Gets the UUID of the module.
* This should usually be different from the UUID in the {@link Header}.
*
* @return the UUID
* @since 2.1.1
*/
@NonNull
UUID uuid();
/**
* Gets the version of the module.
* Gets the {@link Version} of the module.
*
* @return the version
* @return the {@link Version}
* @since 2.1.1
*/
@NonNull
Version version();
@@ -137,6 +193,7 @@ public interface ResourcePackManifest {
* Gets the type of the module.
*
* @return the type
* @since 2.1.1
*/
@NonNull
String type();
@@ -145,6 +202,7 @@ public interface ResourcePackManifest {
* Gets the description of the module.
*
* @return the description
* @since 2.1.1
*/
@NonNull
String description();
@@ -152,28 +210,102 @@ public interface ResourcePackManifest {
/**
* Represents a dependency of a resource pack.
* These are references to other resource packs that must be
* present in order for this resource pack to apply.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/reference/content/addonsreference/examples/addonmanifest?view=minecraft-bedrock-stable#dependencies">
* Microsoft's docs for further details on dependencies.</a>
* @since 2.1.1
*/
interface Dependency {
/**
* Gets the UUID of the dependency.
* Gets the UUID of the resource pack dependency.
*
* @return the uuid
* @since 2.1.1
*/
@NonNull
UUID uuid();
/**
* Gets the version of the dependency.
* Gets the {@link Version} of the dependency.
*
* @return the version
* @return the {@link Version}
* @since 2.1.1
*/
@NonNull
Version version();
}
/**
* Represents a subpack of a resource pack. These are often used for "variants" of the resource pack,
* such as lesser details, or additional features either to be determined by player's taste or adapted to the player device's performance.
* See <a href="https://learn.microsoft.com/en-us/minecraft/creator/documents/utilizingsubpacks">Micoroft's docs</a> for more information.
*/
interface Subpack {
/**
* Gets the folder name where this sub-pack is placed in.
*
* @return the folder name
* @since 2.6.2
*/
@NonNull
String folderName();
/**
* Gets the name of this subpack. Required for each subpack to be valid.
* To make a Bedrock client load any subpack, register the resource pack
* in the {@link SessionLoadResourcePacksEvent} or {@link GeyserDefineResourcePacksEvent} and specify a
* {@link SubpackOption} with the name of the subpack to load.
*
* @return the subpack name
* @since 2.6.2
*/
@NonNull
String name();
/**
* Gets the memory tier of this Subpack, representing how much RAM a device must have to run it.
* Each memory tier requires 0.25 GB of RAM. For example, a memory tier of 0 is no requirement,
* and a memory tier of 4 requires 1GB of RAM.
*
* @return the memory tier
* @since 2.6.2
*/
@Nullable
Float memoryTier();
}
/**
* Represents a setting that is shown client-side that describe what a pack does.
* Multiple setting entries are shown in separate paragraphs.
* @since 2.6.2
*/
interface Setting {
/**
* The type of the setting. Usually just "label".
*
* @return the type
* @since 2.6.2
*/
@NonNull
String type();
/**
* The text shown for the setting.
*
* @return the text content
* @since 2.6.2
*/
@NonNull
String text();
}
/**
* Represents a version of a resource pack.
* @since 2.1.1
*/
interface Version {
@@ -181,6 +313,7 @@ public interface ResourcePackManifest {
* Gets the major version.
*
* @return the major version
* @since 2.1.1
*/
int major();
@@ -188,6 +321,7 @@ public interface ResourcePackManifest {
* Gets the minor version.
*
* @return the minor version
* @since 2.1.1
*/
int minor();
@@ -195,6 +329,7 @@ public interface ResourcePackManifest {
* Gets the patch version.
*
* @return the patch version
* @since 2.1.1
*/
int patch();
@@ -202,6 +337,7 @@ public interface ResourcePackManifest {
* Gets the version formatted as a String.
*
* @return the version string
* @since 2.1.1
*/
@NonNull String toString();
}

View File

@@ -0,0 +1,51 @@
/*
* 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 pack codec that creates a resource
* pack from a URL.
* <p>
* Due to Bedrock limitations, the URL must:
* <ul>
* <li>be a direct download link to a .zip or .mcpack resource pack</li>
* <li>use the application type `application/zip` and set a correct content length</li>
* </ul>
* @since 2.6.2
*/
public abstract class UrlPackCodec extends PackCodec {
/**
* Gets the URL to the resource pack location.
*
* @return the URL of the resource pack
* @since 2.6.2
*/
@NonNull
public abstract String url();
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2025 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.exception;
import java.io.Serial;
/**
* Used to indicate an exception that occurred while handling resource pack registration,
* or during resource pack option validation.
* @since 2.6.2
*/
public class ResourcePackException extends IllegalArgumentException {
@Serial
private static final long serialVersionUID = 1L;
/**
* The {@link Cause} of this exception.
*/
private final Cause cause;
/**
* @param cause the cause of this exception
* @since 2.6.2
*/
public ResourcePackException(Cause cause) {
super(cause.message());
this.cause = cause;
}
/**
* @param cause the cause of this exception
* @param message an additional, more in-depth message about the issue.
* @since 2.6.2
*/
public ResourcePackException(Cause cause, String message) {
super(message);
this.cause = cause;
}
/**
* @return the cause of this exception
* @since 2.6.2
*/
public Cause cause() {
return cause;
}
/**
* Represents different causes with explanatory messages stating which issue occurred.
* @since 2.6.2
*/
public enum Cause {
DUPLICATE("A resource pack with this UUID was already registered!"),
INVALID_PACK("This resource pack is not a valid Bedrock edition resource pack!"),
INVALID_PACK_OPTION("Attempted to register an invalid resource pack option!"),
PACK_NOT_FOUND("No resource pack was found!"),
UNKNOWN_IMPLEMENTATION("Use the resource pack codecs to create resource packs.");
private final String message;
/**
* @return the message of this cause
* @since 2.6.2
*/
public String message() {
return message;
}
Cause(String message) {
this.message = message;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 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.pack.option;
import org.geysermc.geyser.api.GeyserApi;
/**
* Allows specifying a pack priority that decides the order on how packs are sent to the client.
* If two resource packs modify the same texture - for example if one removes the pumpkin overlay and
* the other is just making it translucent, one of the packs will override the other.
* Specifically, the pack with the higher priority will override the pack changes of the lower priority.
* @since 2.6.2
*/
public interface PriorityOption extends ResourcePackOption<Integer> {
PriorityOption HIGHEST = PriorityOption.priority(100);
PriorityOption HIGH = PriorityOption.priority(50);
PriorityOption NORMAL = PriorityOption.priority(0);
PriorityOption LOW = PriorityOption.priority(-50);
PriorityOption LOWEST = PriorityOption.priority(-100);
/**
* Constructs a priority option based on a value between 0 and 10.
* The higher the number, the higher will this pack appear in the resource pack stack.
*
* @param priority an integer that is above 0, but smaller than 10
* @return the priority option
* @since 2.6.2
*/
static PriorityOption priority(int priority) {
if (priority < -100 || priority > 100) {
throw new IllegalArgumentException("Priority must be between 0 and 10 inclusive!");
}
return GeyserApi.api().provider(PriorityOption.class, priority);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 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.pack.option;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.exception.ResourcePackException;
/**
* Represents a resource pack option that can be used to specify how a resource
* pack is sent to Bedrock clients.
* <p>
* Not all options can be applied to all resource packs. For example, you cannot specify
* a specific subpack to be loaded on resource packs that do not have subpacks.
* To see which limitations apply to specific resource pack options, check the javadocs
* or see the {@link #validate(ResourcePack)} method.
* @since 2.6.2
*/
public interface ResourcePackOption<T> {
/**
* @return the option type
* @since 2.6.2
*/
@NonNull Type type();
/**
* @return the value of the option
* @since 2.6.2
*/
@NonNull T value();
/**
* Used to validate a specific options for a pack.
* Some options are not applicable to some packs.
*
* @param pack the resource pack to validate the option for
* @throws ResourcePackException with the {@link ResourcePackException.Cause#INVALID_PACK_OPTION} cause
* @since 2.6.2
*/
void validate(@NonNull ResourcePack pack);
/**
* Represents the different types of resource pack options.
* @since 2.6.2
*/
enum Type {
SUBPACK,
PRIORITY,
FALLBACK
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 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.pack.option;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.pack.ResourcePackManifest;
/**
* Can be used to specify which subpack from a resource pack a player should load.
* Available subpacks can be seen in a resource pack manifest {@link ResourcePackManifest#subpacks()}.
* @since 2.6.2
*/
public interface SubpackOption extends ResourcePackOption<String> {
/**
* Creates a subpack option based on a {@link ResourcePackManifest.Subpack}.
*
* @param subpack the chosen subpack
* @return a subpack option specifying that subpack
* @since 2.6.2
*/
static SubpackOption subpack(ResourcePackManifest.@NonNull Subpack subpack) {
return named(subpack.name());
}
/**
* Creates a subpack option based on a subpack name.
*
* @param subpackName the name of the subpack
* @return a subpack option specifying a subpack with that name
* @since 2.6.2
*/
static SubpackOption named(@NonNull String subpackName) {
return GeyserApi.api().provider(SubpackOption.class, subpackName);
}
/**
* Creates a subpack option with no subpack specified.
*
* @return a subpack option specifying no subpack
* @since 2.6.2
*/
static SubpackOption empty() {
return GeyserApi.api().provider(SubpackOption.class, "");
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 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.pack.option;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.pack.PathPackCodec;
import org.geysermc.geyser.api.pack.UrlPackCodec;
/**
* Can be used for resource packs created with the {@link UrlPackCodec}.
* When a Bedrock client is unable to download a resource pack from a URL, Geyser will, by default,
* serve the resource pack over raknet (as packs are served with the {@link PathPackCodec}).
* This option can be used to disable that behavior, and disconnect the player instead.
* By default, the {@link UrlFallbackOption#TRUE} option is set.
* @since 2.6.2
*/
public interface UrlFallbackOption extends ResourcePackOption<Boolean> {
UrlFallbackOption TRUE = fallback(true);
UrlFallbackOption FALSE = fallback(false);
/**
* Whether to fall back to serving packs over the raknet connection
*
* @param fallback whether to fall back
* @return a UrlFallbackOption with the specified behavior
* @since 2.6.2
*/
static UrlFallbackOption fallback(boolean fallback) {
return GeyserApi.api().provider(UrlFallbackOption.class, fallback);
}
}

View File

@@ -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.permission;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.util.TriState;
/**
* Something capable of checking if a {@link CommandSource} has a permission
*/
@FunctionalInterface
public interface PermissionChecker {
/**
* Checks if the given source has a permission
*
* @param source the {@link CommandSource} whose permissions should be queried
* @param permission the permission node to check
* @return a {@link TriState} as the value of the node. {@link TriState#NOT_SET} generally means that the permission
* node itself was not found, and the source does not have such permission.
* {@link TriState#TRUE} and {@link TriState#FALSE} represent explicitly set values.
*/
@NonNull
TriState hasPermission(@NonNull CommandSource source, @NonNull String permission);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 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.skin;
/**
* Represents a cape.
*
* @param textureUrl The URL of the cape texture
* @param capeId The ID of the cape
* @param capeData The raw cape image data in ARGB format
* @param failed If the cape failed to load, this is for things like fallback capes
*/
public record Cape(String textureUrl, String capeId, byte[] capeData, boolean failed) {
public Cape(String textureUrl, String capeId, byte[] capeData) {
this(textureUrl, capeId, capeData, false);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 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.skin;
/**
* Represents a skin.
*
* @param textureUrl The URL/ID of the skin texture
* @param skinData The raw skin image data in ARGB
* @param failed If the skin failed to load, this is for things like fallback skins
*/
public record Skin(String textureUrl, byte[] skinData, boolean failed) {
public Skin(String textureUrl, byte[] skinData) {
this(textureUrl, skinData, false);
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 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.skin;
/**
* Represents a full package of {@link Skin}, {@link Cape}, and {@link SkinGeometry}.
*/
public record SkinData(Skin skin, Cape cape, SkinGeometry geometry) {
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 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.skin;
/**
* Represents geometry of a skin.
*
* @param geometryName The name of the geometry (JSON)
* @param geometryData The geometry data (JSON)
*/
public record SkinGeometry(String geometryName, String geometryData) {
public static SkinGeometry WIDE = getLegacy(false);
public static SkinGeometry SLIM = getLegacy(true);
/**
* Generate generic geometry
*
* @param isSlim if true, it will be the slimmer alex model
* @return The generic geometry object
*/
private static SkinGeometry getLegacy(boolean isSlim) {
return new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.custom" + (isSlim ? "Slim" : "") + "\"}}", "");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
* 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
@@ -31,11 +31,10 @@ import org.checkerframework.checker.nullness.qual.NonNull;
* Represents the creative menu categories or tabs.
*/
public enum CreativeCategory {
COMMANDS("commands", 1),
CONSTRUCTION("construction", 2),
CONSTRUCTION("construction", 1),
NATURE("nature", 2),
EQUIPMENT("equipment", 3),
ITEMS("items", 4),
NATURE("nature", 5),
NONE("none", 6);
private final String internalName;

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2024-2025 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;
import org.geysermc.geyser.api.GeyserApi;
/**
* An identifying object for representing unique objects.
* This identifier consists of two parts:
* <ul>
* <li>
* a namespace, which is usually a name identifying your work
* </li>
* <li>
* a path, which holds a value.
* </li>
* </ul>
*
* Examples of identifiers:
* <ul>
* <li>{@code minecraft:fox}</li>
* <li>{@code geysermc:one_fun_example}</li>
* </ul>
*
* If this identifier is referencing anything not in the
* vanilla Minecraft game, the namespace cannot be "minecraft".
* Further, paths cannot contain colons ({@code :}).
*
* @since 2.9.0
*/
public interface Identifier {
/**
* The namespace for Minecraft.
* @since 2.9.0
*/
String DEFAULT_NAMESPACE = "minecraft";
/**
* Attempts to create a new identifier from a namespace and path.
*
* @return the identifier for this namespace and path
* @throws IllegalArgumentException if either namespace or path are invalid.
* @since 2.9.0
*/
static Identifier of(@NonNull String namespace, @NonNull String path) {
return GeyserApi.api().provider(Identifier.class, namespace, path);
}
/**
* Attempts to create a new identifier from a string representation.
*
* @return the identifier for this namespace and path
* @throws IllegalArgumentException if either the namespace or path are invalid
* @since 2.9.0
*/
static Identifier of(String identifier) {
String[] split = identifier.split(":");
String namespace;
String path;
if (split.length == 1) {
namespace = DEFAULT_NAMESPACE;
path = split[0];
} else if (split.length == 2) {
namespace = split[0];
path = split[1];
} else {
throw new IllegalArgumentException("':' in identifier path: " + identifier);
}
return of(namespace, path);
}
/**
* @return the namespace of this identifier.
* @since 2.9.0
*/
String namespace();
/**
* @return the path of this identifier.
* @since 2.9.0
*/
String path();
/**
* Checks whether this identifier is using the "minecraft" namespace.
* @since 2.9.0
*/
default boolean vanilla() {
return namespace().equals(DEFAULT_NAMESPACE);
}
}

View File

@@ -34,7 +34,7 @@ public interface MinecraftVersion {
/**
* Gets the Minecraft version as a String.
* Example: "1.20.2", or "1.20.40/1.20.41"
* Example formats: "1.21", "1.21.1", "1.21.22"
*
* @return the version string
*/