diff --git a/gradle.properties b/gradle.properties index 91a322c..9ab218a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ loom_version=1.16-SNAPSHOT fabric_api_version=0.145.1+26.1 # Mod Properties -mod_version=1.0.0 +mod_version=1.1.0 maven_group=dev.loat archives_base_name=msmp-entity-mod diff --git a/src/main/java/dev/loat/msmp_entity/MSMPEntity.java b/src/main/java/dev/loat/msmp_entity/MSMPEntity.java index d264ffe..35188c2 100644 --- a/src/main/java/dev/loat/msmp_entity/MSMPEntity.java +++ b/src/main/java/dev/loat/msmp_entity/MSMPEntity.java @@ -3,8 +3,7 @@ import dev.loat.msmp.MSMPNamespace; import dev.loat.msmp.MSMPServer; import dev.loat.msmp_entity.logging.Logger; -import dev.loat.msmp_entity.msmp.methods.Methods; -import dev.loat.msmp_entity.msmp.notifications.Notifications; +import dev.loat.msmp_entity.msmp.endpoints.Endpoints; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -38,8 +37,7 @@ public class MSMPEntity implements ModInitializer { public void onInitialize() { Logger.setLoggerClass(MSMPEntity.class); - Methods.register(NS); - Notifications.register(NS, () -> msmp); + Endpoints.register(NS, () -> msmp); ServerLifecycleEvents.SERVER_STARTED.register(server -> { NS.attach(server); diff --git a/src/main/java/dev/loat/msmp_entity/msmp/endpoints/Endpoints.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/Endpoints.java new file mode 100644 index 0000000..d60fc0a --- /dev/null +++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/Endpoints.java @@ -0,0 +1,58 @@ +package dev.loat.msmp_entity.msmp.endpoints; + +import dev.loat.msmp.MSMPNamespace; +import dev.loat.msmp.MSMPServer; +import dev.loat.msmp_entity.msmp.endpoints.dimension.Dimension; +import dev.loat.msmp_entity.msmp.endpoints.dimension.DimensionSet; +import dev.loat.msmp_entity.msmp.endpoints.dimension.changed.DimensionChangedAdd; +import dev.loat.msmp_entity.msmp.endpoints.dimension.changed.DimensionChangedRemove; +import dev.loat.msmp_entity.msmp.endpoints.dimension.notification.changed.DimensionChanged; +import dev.loat.msmp_entity.msmp.endpoints.health.Health; +import dev.loat.msmp_entity.msmp.endpoints.health.HealthSet; +import dev.loat.msmp_entity.msmp.endpoints.items.Items; +import dev.loat.msmp_entity.msmp.endpoints.items.ItemsSet; +import dev.loat.msmp_entity.msmp.endpoints.position.Position; +import dev.loat.msmp_entity.msmp.endpoints.position.PositionSet; +import dev.loat.msmp_entity.msmp.endpoints.rotation.Rotation; +import dev.loat.msmp_entity.msmp.endpoints.rotation.RotationSet; +import dev.loat.msmp_entity.msmp.endpoints.uuid.UUID; + +import java.util.function.Supplier; + + +/** + * Central registration point for all {@code entity} MSMP endpoints. + * + *
Each endpoint is implemented in its own sub-package and registered here.
+ */ +public class Endpoints { + private Endpoints() {} + + /** + * Registers all endpoints on the given {@link MSMPNamespace}. + * + * @param namespace The namespace to register all endpoints under + * @param msmpServer A supplier for the MSMPServer instance, used by some endpoints to subscribe to server events + */ + public static void register(MSMPNamespace namespace, SupplierReturns the dimension of any loaded entity. - * Players can be looked up by UUID or name; all other entities require a UUID.
- * + * + *Returns the current dimension of any loaded entity.
+ * *Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:dimension",
- * "params": [{ "name": "Steve" }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:dimension",
+ * "params": [{ "name": "Steve" }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "dimension": "minecraft:overworld" }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "dimension": "minecraft:overworld"
+ * }
+ *
*/
public class Dimension {
private Dimension() {}
/**
- * Registers the {@code entity:dimension} method on the given {@link MSMPNamespace}.
+ * Registers the {@code entity:dimension} method.
*
- * Entity lookup is delegated to {@link EntityResolver#resolveEntity}. - * The dimension is returned as a resource key string via {@code identifier().toString()}, - * e.g. {@code minecraft:overworld}, {@code minecraft:the_nether}, {@code minecraft:the_end}.
+ *The dimension is returned as a resource key string, ex. {@code minecraft:overworld}, + * {@code minecraft:the_nether}, {@code minecraft:the_end}.
* * @param namespace The namespace to register this method under */ public static void register(MSMPNamespace namespace) { - namespace.method("dimension", + namespace.method( + "dimension", EntityRequest.SCHEMA, DimensionResponse.SCHEMA, "Returns the current dimension of any loaded entity by UUID, or a player by name", @@ -50,7 +57,7 @@ public static void register(MSMPNamespace namespace) { entity.level().dimension().identifier().toString() ); } catch (IllegalArgumentException e) { - Logger.warning("entity:dimension - " + e.getMessage()); + RPCConnectionLogger.warning(client.connectionId(), "entity:dimension - " + e.getMessage()); throw e; } } diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionResponse.java similarity index 74% rename from src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionResponse.java rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionResponse.java index f5191d5..bc2ceb7 100644 --- a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionResponse.java +++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionResponse.java @@ -1,23 +1,24 @@ -package dev.loat.msmp_entity.msmp.methods.dimension; +package dev.loat.msmp_entity.msmp.endpoints.dimension; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import dev.loat.msmp_entity.msmp.components.EntityRef; + import net.minecraft.server.jsonrpc.api.Schema; /** - * Response payload shared between {@code entity:dimension} and {@code entity:dimension/set}. + * Response payload for the {@code entity:dimension} and {@code entity:dimension/set} method. * - *Example JSON representation:
- *{@code
+ * Example response:
+ *
* {
- * "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
+ * "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
* "dimension": "minecraft:overworld"
* }
- * }
+ *
*
- * @param entity The entity reference; always includes UUID, name only for players
+ * @param entity The entity reference; always includes UUID, name only for players
* @param dimension The resource key of the dimension the entity is currently in
*/
public record DimensionResponse(EntityRef entity, String dimension) {
@@ -37,3 +38,4 @@ public record DimensionResponse(EntityRef entity, String dimension) {
.withField("entity", EntityRef.SCHEMA)
.withField("dimension", Schema.STRING_SCHEMA);
}
+
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionSet.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionSet.java
similarity index 80%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionSet.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionSet.java
index 1786c01..c258395 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/DimensionSet.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/DimensionSet.java
@@ -1,14 +1,16 @@
-package dev.loat.msmp_entity.msmp.methods.dimension;
+package dev.loat.msmp_entity.msmp.endpoints.dimension;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.RPCConnectionLogger;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
+
/**
* Registers the {@code entity:dimension/set} MSMP method.
*
@@ -16,13 +18,20 @@
*
* Example request:
*{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:dimension/set",
- * "params": [{ "name": "Steve", "dimension": "minecraft:the_nether" }] }
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:dimension/set",
+ * "params": [{ "name": "Steve", "dimension": "minecraft:the_nether" }]
+ * }
* }
*
* Example response:
*{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "dimension": "minecraft:the_nether" }
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "dimension": "minecraft:the_nether"
+ * }
* }
*/
public class DimensionSet {
@@ -30,10 +39,9 @@ public class DimensionSet {
private DimensionSet() {}
/**
- * Registers the {@code entity:dimension/set} method on the given {@link MSMPNamespace}.
+ * Registers the {@code entity:dimension/set} method.
*
- * The entity is teleported to the target dimension at its current position and rotation. - * Throws {@link IllegalArgumentException} if the dimension identifier is unknown.
+ *The entity is teleported to the target dimension at its current position and rotation.
* * @param namespace The namespace to register this method under */ @@ -46,10 +54,10 @@ public static void register(MSMPNamespace namespace) { try { Entity entity = EntityResolver.resolveEntity(server, params); - Identifier dimId = Identifier.parse(params.dimension()); + Identifier dimensionId = Identifier.parse(params.dimension()); ResourceKeyTransfers the entity to the given dimension at its current position.
* *Example JSON representation:
- *{@code
+ *
* { "name": "Steve", "dimension": "minecraft:the_nether" }
- * }
+ *
*
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
* @param dimension The target dimension resource key (e.g. {@code minecraft:the_nether})
*/
public record DimensionSetRequest(
@@ -46,3 +47,4 @@ public record DimensionSetRequest(
.withField("name", Schema.STRING_SCHEMA)
.withField("dimension", Schema.STRING_SCHEMA);
}
+
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/changed/DimensionChangedAdd.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/changed/DimensionChangedAdd.java
new file mode 100644
index 0000000..fda0ae4
--- /dev/null
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/dimension/changed/DimensionChangedAdd.java
@@ -0,0 +1,89 @@
+package dev.loat.msmp_entity.msmp.endpoints.dimension.changed;
+
+import dev.loat.msmp.MSMPNamespace;
+import dev.loat.msmp_entity.logging.RPCConnectionLogger;
+import dev.loat.msmp_entity.msmp.components.EntityRef;
+import dev.loat.msmp_entity.msmp.components.EntityRequest;
+import dev.loat.msmp_entity.msmp.components.EntityResolver;
+import dev.loat.msmp_entity.msmp.subscription.SubscribeRequest;
+import dev.loat.msmp_entity.msmp.subscription.SubscribeResponse;
+import dev.loat.msmp_entity.msmp.subscription.SubscriptionManager;
+
+import net.minecraft.world.entity.Entity;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+
+/**
+ * Registers the {@code entity:dimension/changed/add} MSMP subscription method.
+ *
+ * Adds specified entities to the dimension change notification subscription list. + * When a subscribed entity changes dimensions, clients receive notifications. This method + * allows clients to subscribe to receiving notifications for the given entities.
+ * + *Example request:
+ *
+ * {
+ * "jsonrpc": "2.0", "id": 1, "method": "entity:dimension/changed/add",
+ * "params": [{ "entities": [{ "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5" }] }]
+ * }
+ *
+ *
+ * Example response:
+ *
+ * { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" }
+ *
+ */
+public class DimensionChangedAdd {
+
+ private DimensionChangedAdd() {}
+
+ /**
+ * Registers the {@code entity:dimension/changed/add} method on the given {@link MSMPNamespace}.
+ *
+ * Resolves the provided entities and adds them to the dimension change notification + * subscription list. If the entity list is empty, returns an empty response immediately. + * Throws {@link IllegalArgumentException} if any entity cannot be resolved.
+ * + * @param namespace The namespace to register this method under + */ + public static void register(MSMPNamespace namespace) { + namespace.method( + "dimension/changed/add", + SubscribeRequest.SCHEMA, + SubscribeResponse.SCHEMA, + "Add entities to the dimension change notification list", + (server, params, client) -> { + if (params.entities().isEmpty()) { + return new SubscribeResponse(List.of()); + } + + SubscriptionManager manager = SubscriptionManager.get("entity:notification/dimension/changed"); + SetRemoves specified entities from the dimension change notification subscription list. + * When a subscribed entity changes dimensions, clients receive notifications. This method + * allows clients to unsubscribe from receiving further notifications for the given entities.
+ * + *Example request:
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:dimension/changed/remove",
+ * "params": [{ "entities": [{ "uuid": "069a79f4-44e9-4726-a5be-fca90e38aaf5" }] }]
+ * }
+ *
+ *
+ * Example response:
+ *
+ * { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" }
+ *
+ */
+public class DimensionChangedRemove {
+
+ private DimensionChangedRemove() {}
+
+ /**
+ * Registers the {@code entity:dimension/changed/remove} method on the given {@link MSMPNamespace}.
+ *
+ * Resolves the provided entities and removes them from the dimension change notification + * subscription list. If the entity list is empty, returns an empty response immediately. + * Throws {@link IllegalArgumentException} if any entity cannot be resolved.
+ * + * @param namespace The namespace to register this method under + */ + public static void register(MSMPNamespace namespace) { + namespace.method( + "dimension/changed/remove", + SubscribeRequest.SCHEMA, + SubscribeResponse.SCHEMA, + "Remove entities from the dimension change notification list", + (server, params, client) -> { + if (params.entities().isEmpty()) { + return new SubscribeResponse(List.of()); + } + + SubscriptionManager manager = SubscriptionManager.get("entity:notification/dimension/changed"); + SetFires when an entity changes dimension. Clients can subscribe to this notification to receive + * updates whenever a specified entity changes dimensions.
+ * + *Example notification payload:
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "origin": "minecraft:overworld",
+ * "destination": "minecraft:the_nether"
+ * }
+ *
+ */
+public class DimensionChanged {
+
+ private DimensionChanged() {}
+
+ /**
+ * Registers the {@code entity:dimension/changed} notification method and its associated event listeners.
+ *
+ * Listens for entity dimension change events and dispatches notifications to subscribed clients. + * The notification is only sent if the entity that changed dimensions is currently subscribed to + * receive dimension change notifications.
+ * + * @param namespace The namespace to register this notification under + * @param msmpServer A supplier that provides access to the MSMPServer instance for sending notifications + */ + public static void register( + MSMPNamespace namespace, + SupplierExample JSON representation:
- *{@code
+ *
* {
* "entity": { "id": "069a...", "name": "Steve" },
* "from": "minecraft:overworld",
* "to": "minecraft:the_nether"
* }
- * }
+ *
*
* @param entity The entity that changed dimension
* @param from The dimension the entity came from
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/Health.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/Health.java
similarity index 89%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/health/Health.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/Health.java
index cab83a2..1b496d9 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/Health.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/Health.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.health;
+package dev.loat.msmp_entity.msmp.endpoints.health;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
@@ -15,21 +15,23 @@
* Players can be looked up by UUID or name; all other entities require a UUID.
*
* Example request:
- *{@code
+ *
* {
- * "jsonrpc": "2.0", "id": 1, "method": "entity:health",
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:health",
* "params": [{ "name": "Steve" }]
* }
- * }
+ *
*
* Example response:
- *{@code
+ *
* {
* "entity": { "id": "069a...", "name": "Steve" },
* "health": 20.0,
* "max_health": 20.0
* }
- * }
+ *
*/
public class Health {
@@ -45,10 +47,11 @@ private Health() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("health",
+ namespace.method(
+ "health",
EntityRequest.SCHEMA,
HealthResponse.SCHEMA,
- "Returns the current and maximum health of any LivingEntity by UUID, or a player by name",
+ "Returns the current and maximum health of any LivingEntity",
(server, params, client) -> {
try {
LivingEntity living = EntityResolver.resolveLivingEntity(server, params);
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthResponse.java
similarity index 70%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthResponse.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthResponse.java
index ef7ee40..fc4f61d 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthResponse.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthResponse.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.health;
+package dev.loat.msmp_entity.msmp.endpoints.health;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -10,25 +10,17 @@
/**
* Response payload shared between {@code entity:health} and {@code entity:health/set}.
*
- * Example JSON representations:
- *{@code
- * // Player:
+ * Example response:
+ *
* {
- * "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
- * "health": 20.0,
+ * "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
+ * "health": 20.0,
* "max_health": 20.0
* }
+ *
*
- * // Non-player entity:
- * {
- * "entity": { "id": "1b3e9f2a-12cd-4b56-a832-ff1234567890" },
- * "health": 14.0,
- * "max_health": 20.0
- * }
- * }
- *
- * @param entity Reference to the entity; always includes UUID, name only for players
- * @param health The entity's current health points
+ * @param entity Reference to the entity; always includes UUID, name only for players
+ * @param health The entity's current health points
* @param maxHealth The entity's maximum health points
*/
public record HealthResponse(EntityRef entity, double health, double maxHealth) {
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSet.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSet.java
similarity index 79%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSet.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSet.java
index 9cf825d..7782ac8 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSet.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSet.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.health;
+package dev.loat.msmp_entity.msmp.endpoints.health;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
@@ -16,24 +16,38 @@
* Returns the actual values after the update.
*
* Example requests:
- *{@code
- * // Set only health:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:health/set",
- * "params": [{ "name": "Steve", "health": 15.0 }] }
- *
- * // Set only max_health:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:health/set",
- * "params": [{ "name": "Steve", "max_health": 40.0 }] }
- *
- * // Set both:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:health/set",
- * "params": [{ "name": "Steve", "health": 15.0, "max_health": 40.0 }] }
- * }
+ *
+ * // Only set health
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:health/set",
+ * "params": [{ "name": "Steve", "health": 15.0 }]
+ * }
+ * // Only set max health
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:health/set",
+ * "params": [{ "name": "Steve", "max_health": 40.0 }]
+ * }
+ * // Set both
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:health/set",
+ * "params": [{ "name": "Steve", "health": 15.0, "max_health": 40.0 }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "health": 15.0, "max_health": 40.0 }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "health": 15.0,
+ * "max_health": 40.0
+ * }
+ *
*/
public class HealthSet {
@@ -47,13 +61,11 @@ private HealthSet() {}
* by Minecraft. If {@code health} is set, it is applied after {@code max_health} to ensure
* the value is within the valid range.
*
- * Throws {@link IllegalArgumentException} if neither {@code health} nor - * {@code max_health} is provided, or if the entity is not a {@link LivingEntity}.
- * * @param namespace The namespace to register this method under */ public static void register(MSMPNamespace namespace) { - namespace.method("health/set", + namespace.method( + "health/set", HealthSetRequest.SCHEMA, HealthResponse.SCHEMA, "Partially updates the health and/or maximum health of any LivingEntity", diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSetRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSetRequest.java similarity index 82% rename from src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSetRequest.java rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSetRequest.java index 376c614..9c0af59 100644 --- a/src/main/java/dev/loat/msmp_entity/msmp/methods/health/HealthSetRequest.java +++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/health/HealthSetRequest.java @@ -1,4 +1,4 @@ -package dev.loat.msmp_entity.msmp.methods.health; +package dev.loat.msmp_entity.msmp.endpoints.health; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -14,16 +14,19 @@ *At least one of {@code health} or {@code max_health} must be present. * Only the provided fields are updated; omitted fields remain unchanged.
* - *Example JSON representations:
- *{@code
+ * Example request:
+ *
+ * // Only health is set
* { "id": "069a...", "health": 15.0 }
+ * // Only max health is set
* { "id": "069a...", "max_health": 40.0 }
+ * // Both are set
* { "name": "Steve", "health": 15.0, "max_health": 40.0 }
- * }
- *
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
- * @param health The new health value to set, if provided
+ *
+ *
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
+ * @param health The new health value to set, if provided
* @param maxHealth The new maximum health value to set, if provided
*/
public record HealthSetRequest(
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/Inventory.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/Items.java
similarity index 53%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/Inventory.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/Items.java
index b6c9509..a3ebae1 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/Inventory.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/Items.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.inventory;
+package dev.loat.msmp_entity.msmp.endpoints.items;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -8,12 +8,13 @@
import dev.loat.msmp_entity.logging.Logger;
import dev.loat.msmp_entity.msmp.components.EntityRequest;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
/**
- * Registers the {@code entity:inventory} MSMP method.
+ * Registers the {@code entity:items} MSMP method.
*
* Returns all occupied inventory slots of an online player in the Vanilla NBT * {@code Inventory} format, equivalent to {@code /data get entity @s Inventory}.
@@ -27,28 +28,36 @@ * * *Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:inventory",
- * "params": [{ "name": "Steve" }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:items",
+ * "params": [{ "name": "Steve" }]
+ * }
+ *
*
* Example response:
- *{@code
+ *
* {
* "entity": { "id": "069a...", "name": "Steve" },
* "inventory": [
* { "Slot": 0, "id": "minecraft:diamond_sword", "count": 1, "components": { ... } },
- * { "Slot": 36, "id": "minecraft:iron_boots", "count": 1 }
- * ]
+ * { "Slot": 20, "id": "minecraft:iron_boots", "count": 1 }
+ * ],
+ * "equipment": {
+ * "head": { "id": "minecraft:diamond_helmet", "count": 1 },
+ * "feet": { "id": "minecraft:diamond_boots", "count": 1 }
+ * }
* }
- * }
+ *
*/
-public class Inventory {
+public class Items {
- private Inventory() {}
+ private Items() {}
/**
- * Registers the {@code entity:inventory} method on the given {@link MSMPNamespace}.
+ * Registers the {@code entity:items} method on the given {@link MSMPNamespace}.
*
* Entity lookup is delegated to {@link EntityResolver#resolvePlayer} since only * players have an inventory. Each occupied slot is serialized via {@link ItemStack#CODEC} @@ -58,19 +67,21 @@ private Inventory() {} * @param namespace The namespace to register this method under */ public static void register(MSMPNamespace namespace) { - namespace.method("inventory", + namespace.method( + "items", EntityRequest.SCHEMA, - InventoryResponse.SCHEMA, + ItemsResponse.SCHEMA, "Returns all occupied inventory slots of an online player in Vanilla NBT format", (server, params, client) -> { try { Player player = EntityResolver.resolvePlayer(server, params); - net.minecraft.world.entity.player.Inventory inv = player.getInventory(); + Inventory items = player.getInventory(); - JsonArray inventory = new JsonArray(); + JsonArray inventoryItems = new JsonArray(); + JsonObject equipmentItems = new JsonObject(); - for (int slot = 0; slot < inv.getContainerSize(); slot++) { - ItemStack stack = inv.getItem(slot); + for (int slot = 0; slot < items.getContainerSize(); slot++) { + ItemStack stack = items.getItem(slot); if (stack.isEmpty()) continue; final int finalSlot = slot; @@ -81,13 +92,29 @@ public static void register(MSMPNamespace namespace) { )); JsonObject entry = itemJson.getAsJsonObject().deepCopy(); - entry.addProperty("Slot", slot); - inventory.add(entry); + entry.addProperty("count", entry.has("count") ? entry.get("count").getAsInt() : 1); + + if (slot >= 36 && slot <= 40) { + String equipmentKey = switch (slot) { + case 36 -> "feet"; + case 37 -> "legs"; + case 38 -> "chest"; + case 39 -> "head"; + case 40 -> "offhand"; + default -> null; + }; + if (equipmentKey != null) { + equipmentItems.add(equipmentKey, entry); + } + } else { + entry.addProperty("Slot", slot); + inventoryItems.add(entry); + } } - return new InventoryResponse(EntityResolver.toEntityRef(player), inventory); + return new ItemsResponse(EntityResolver.toEntityRef(player), inventoryItems, equipmentItems); } catch (IllegalArgumentException e) { - Logger.warning("entity:inventory - " + e.getMessage()); + Logger.warning("entity:items - " + e.getMessage()); throw e; } } diff --git a/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsResponse.java new file mode 100644 index 0000000..49a907b --- /dev/null +++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsResponse.java @@ -0,0 +1,73 @@ +package dev.loat.msmp_entity.msmp.endpoints.items; + +import com.google.gson.JsonElement; +import com.mojang.serialization.Codec; +import com.mojang.serialization.Dynamic; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import dev.loat.msmp_entity.msmp.components.EntityRef; +import net.minecraft.server.jsonrpc.api.Schema; + + +/** + * Response payload shared between {@code entity:items} and {@code entity:items/set}. + * + *
The {@code inventory} field mirrors the Vanilla NBT {@code Inventory} format exactly — + * each entry contains {@code Slot}, {@code id}, {@code count}, and optionally {@code components}.
+ * + *The {@code equipment} field is an object with keys for each equipped item slot: + * {@code head}, {@code chest}, {@code legs}, {@code feet}, {@code offhand}.
+ * + *Example JSON representation:
+ *{@code
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "inventory": [
+ * { "Slot": 0, "id": "minecraft:diamond_sword", "count": 1, "components": { ... } },
+ * { "Slot": 20, "id": "minecraft:iron_boots", "count": 1 }
+ * ],
+ * "equipment": {
+ * "head": { "id": "minecraft:diamond_helmet", "count": 1 },
+ * "feet": { "id": "minecraft:diamond_boots", "count": 1 }
+ * }
+ * }
+ * }
+ *
+ * @param entity The entity reference; always includes UUID, name only for players
+ * @param inventory The occupied inventory slots in Vanilla NBT format
+ * @param equipment The equipped items keyed by slot name (head, chest, legs, feet, offhand)
+ */
+public record ItemsResponse(EntityRef entity, JsonElement inventory, JsonElement equipment) {
+
+ /**
+ * Codec for passing {@link JsonElement} through the serialization pipeline without modification.
+ */
+ public static final CodecPartially updates an online player's inventory using a diff approach — * only the provided slots are modified, all others remain unchanged. @@ -21,31 +23,36 @@ *
To clear a slot, provide {@code "id": "minecraft:air"}.
* *Example request:
- *{@code
+ *
* {
- * "jsonrpc": "2.0", "id": 1, "method": "entity:inventory/set",
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:items/set",
* "params": [{
* "name": "Steve",
* "inventory": [
* { "Slot": 0, "id": "minecraft:diamond_sword", "count": 1 },
* { "Slot": 9, "id": "minecraft:air", "count": 0 }
- * ]
+ * ],
+ * "equipment": {
+ * "head": { "id": "minecraft:diamond_helmet", "count": 1 }
+ * }
* }]
* }
- * }
+ *
*
* Example response:
- *{@code
+ *
* {
* "entity": { "id": "069a...", "name": "Steve" },
* "inventory": [ ... ]
* }
- * }
+ *
*/
-public class InventorySet {
+public class ItemsSet {
/**
- * Registers the {@code entity:inventory/set} method on the given {@link MSMPNamespace}.
+ * Registers the {@code entity:items/set} method on the given {@link MSMPNamespace}.
*
* Each entry in the {@code inventory} array must contain a {@code Slot} key (integer). * The {@code Slot} key is stripped before passing the entry to {@link ItemStack#CODEC} for @@ -57,12 +64,13 @@ public class InventorySet { * @param namespace The namespace to register this method under */ public static void register(MSMPNamespace namespace) { - namespace.method("inventory/set", - InventorySetRequest.SCHEMA, - InventoryResponse.SCHEMA, + namespace.method( + "items/set", + ItemsSetRequest.SCHEMA, + ItemsResponse.SCHEMA, "Partially updates an online player's inventory using a diff approach", (server, params, client) -> { - InventorySetRequest req = params; + ItemsSetRequest req = params; try { Player player = EntityResolver.resolvePlayer(server, req); net.minecraft.world.entity.player.Inventory inv = player.getInventory(); @@ -103,8 +111,50 @@ public static void register(MSMPNamespace namespace) { inv.setItem(slot, stack); } - // Re-serialize full inventory + if (req.equipment().isJsonObject()) { + var equipmentObj = req.equipment().getAsJsonObject(); + var equipmentSlots = Map.ofEntries( + Map.entry("feet", 36), + Map.entry("legs", 37), + Map.entry("chest", 38), + Map.entry("head", 39), + Map.entry("offhand", 40) + ); + + for (var key : equipmentObj.keySet()) { + if (!equipmentSlots.containsKey(key)) { + throw new IllegalArgumentException( + "Invalid equipment slot '%s' — must be one of: head, chest, legs, feet, offhand".formatted(key) + ); + } + + int slot = equipmentSlots.get(key); + JsonElement itemElement = equipmentObj.get(key); + + if (!itemElement.isJsonObject()) { + throw new IllegalArgumentException("Equipment entry for '%s' must be a JSON object".formatted(key)); + } + + JsonObject entry = itemElement.getAsJsonObject().deepCopy(); + + // Clear the slot if no id given or id is minecraft:air + boolean isEmpty = !entry.has("id") + || entry.get("id").getAsString().equals("minecraft:air"); + + ItemStack stack = isEmpty ? ItemStack.EMPTY : ItemStack.CODEC + .decode(ctx, entry) + .getOrThrow(err -> new IllegalArgumentException( + "Failed to deserialize equipment for '%s': %s".formatted(key, err) + )) + .getFirst(); + + inv.setItem(slot, stack); + } + } + JsonArray inventory = new JsonArray(); + JsonObject equipment = new JsonObject(); + for (int slot = 0; slot < containerSize; slot++) { ItemStack stack = inv.getItem(slot); if (stack.isEmpty()) continue; @@ -117,13 +167,28 @@ public static void register(MSMPNamespace namespace) { )); JsonObject responseEntry = itemJson.getAsJsonObject().deepCopy(); - responseEntry.addProperty("Slot", slot); - inventory.add(responseEntry); + + if (slot >= 36 && slot <= 40) { + String equipmentKey = switch (slot) { + case 36 -> "feet"; + case 37 -> "legs"; + case 38 -> "chest"; + case 39 -> "head"; + case 40 -> "offhand"; + default -> null; + }; + if (equipmentKey != null) { + equipment.add(equipmentKey, responseEntry); + } + } else { + responseEntry.addProperty("Slot", slot); + inventory.add(responseEntry); + } } - return new InventoryResponse(EntityResolver.toEntityRef(player), inventory); + return new ItemsResponse(EntityResolver.toEntityRef(player), inventory, equipment); } catch (IllegalArgumentException e) { - Logger.warning("entity:inventory/set - " + e.getMessage()); + Logger.warning("entity:items/set - " + e.getMessage()); throw e; } } diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventorySetRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsSetRequest.java similarity index 53% rename from src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventorySetRequest.java rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsSetRequest.java index f24a9bc..7167551 100644 --- a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventorySetRequest.java +++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/items/ItemsSetRequest.java @@ -1,4 +1,4 @@ -package dev.loat.msmp_entity.msmp.methods.inventory; +package dev.loat.msmp_entity.msmp.endpoints.items; import com.google.gson.JsonElement; import com.mojang.serialization.Codec; @@ -19,24 +19,29 @@ * To clear a slot, provide {@code "id": "minecraft:air"}.
* *Example JSON representation:
- *{@code
+ *
* {
* "name": "Steve",
* "inventory": [
* { "Slot": 0, "id": "minecraft:diamond_sword", "count": 1 },
* { "Slot": 9, "id": "minecraft:air", "count": 0 }
- * ]
+ * ],
+ * "equipment": {
+ * "head": { "id": "minecraft:diamond_helmet", "count": 1 }
+ * }
* }
- * }
+ *
*
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
* @param inventory The list of slot updates in Vanilla NBT format
+ * @param equipment The equipment updates keyed by slot name (head, chest, legs, feet, offhand)
*/
-public record InventorySetRequest(
+public record ItemsSetRequest(
OptionalExample request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:position",
- * "params": [{ "name": "Steve" }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:position",
+ * "params": [{ "name": "Steve" }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "position": [128.5, 64.0, -32.3] }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "position": [128.5, 64.0, -32.3]
+ * }
+ *
*/
public class Position {
@@ -38,10 +47,11 @@ private Position() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("position",
+ namespace.method(
+ "position",
EntityRequest.SCHEMA,
PositionResponse.SCHEMA,
- "Returns the current position of any loaded entity by UUID, or a player by name",
+ "Returns the current position of any loaded entity",
(server, params, client) -> {
try {
Entity entity = EntityResolver.resolveEntity(server, params);
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionResponse.java
similarity index 89%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionResponse.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionResponse.java
index 578968e..be18b01 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionResponse.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionResponse.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.position;
+package dev.loat.msmp_entity.msmp.endpoints.position;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -10,15 +10,15 @@
/**
- * Response payload shared between {@code entity:position} and {@code entity:position/set}.
+ * Response payload for {@code entity:position} and {@code entity:position/set}.
*
* Example JSON representation:
- *{@code
+ *
* {
* "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
* "position": [128.5, 64.0, -32.3]
* }
- * }
+ *
*
* @param entity The entity reference; always includes UUID, name only for players
* @param position The entity's position as {@code [x, y, z]}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSet.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSet.java
similarity index 86%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSet.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSet.java
index 1ce3ec6..48e8af0 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSet.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSet.java
@@ -1,8 +1,9 @@
-package dev.loat.msmp_entity.msmp.methods.position;
+package dev.loat.msmp_entity.msmp.endpoints.position;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
@@ -14,15 +15,22 @@
* Teleports the entity to the given position within its current dimension.
* *Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:position/set",
- * "params": [{ "name": "Steve", "position": [100.0, 64.0, 200.0] }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:position/set",
+ * "params": [{ "name": "Steve", "position": [100.0, 64.0, 200.0] }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "position": [100.0, 64.0, 200.0] }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "position": [100.0, 64.0, 200.0]
+ * }
+ *
*/
public class PositionSet {
@@ -37,7 +45,8 @@ private PositionSet() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("position/set",
+ namespace.method(
+ "position/set",
PositionSetRequest.SCHEMA,
PositionResponse.SCHEMA,
"Teleports any loaded entity to the given position within its current dimension",
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSetRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSetRequest.java
similarity index 83%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSetRequest.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSetRequest.java
index 43c9309..9b5076d 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/position/PositionSetRequest.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/position/PositionSetRequest.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.position;
+package dev.loat.msmp_entity.msmp.endpoints.position;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -14,12 +14,15 @@
* Request payload for the {@code entity:position/set} method.
*
* Example JSON representation:
- *{@code
- * { "name": "Steve", "position": [100.0, 64.0, 200.0] }
- * }
+ *
+ * {
+ * "name": "Steve",
+ * "position": [100.0, 64.0, 200.0]
+ * }
+ *
*
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
* @param position The target position as {@code [x, y, z]}
*/
public record PositionSetRequest(
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/Rotation.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/Rotation.java
similarity index 81%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/Rotation.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/Rotation.java
index 0bddaf8..48bce37 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/Rotation.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/Rotation.java
@@ -1,9 +1,10 @@
-package dev.loat.msmp_entity.msmp.methods.rotation;
+package dev.loat.msmp_entity.msmp.endpoints.rotation;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
import dev.loat.msmp_entity.msmp.components.EntityRequest;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+
import net.minecraft.world.entity.Entity;
import java.util.List;
@@ -16,15 +17,22 @@
* Players can be looked up by UUID or name; all other entities require a UUID.
*
* Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:rotation",
- * "params": [{ "name": "Steve" }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:rotation",
+ * "params": [{ "name": "Steve" }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "rotation": [90.0, -15.0] }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "rotation": [90.0, -15.0]
+ * }
+ *
*/
public class Rotation {
@@ -39,7 +47,8 @@ private Rotation() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("rotation",
+ namespace.method(
+ "rotation",
EntityRequest.SCHEMA,
RotationResponse.SCHEMA,
"Returns the current rotation of any loaded entity by UUID, or a player by name",
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationResponse.java
similarity index 84%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationResponse.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationResponse.java
index e9622e6..a0f05fd 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationResponse.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationResponse.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.rotation;
+package dev.loat.msmp_entity.msmp.endpoints.rotation;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -10,17 +10,17 @@
/**
- * Response payload shared between {@code entity:rotation} and {@code entity:rotation/set}.
+ * Response payload for {@code entity:rotation} and {@code entity:rotation/set}.
*
* Example JSON representation:
- *{@code
+ *
* {
* "entity": { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" },
* "rotation": [90.0, -15.0]
* }
- * }
+ *
*
- * @param entity The entity reference; always includes UUID, name only for players
+ * @param entity The entity reference; always includes UUID, name only for players
* @param rotation The entity's rotation as {@code [yaw, pitch]}
*/
public record RotationResponse(EntityRef entity, ListSets the rotation of any loaded entity. Position and dimension are preserved.
* *Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:rotation/set",
- * "params": [{ "name": "Steve", "rotation": [90.0, -15.0] }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:rotation/set",
+ * "params": [{ "name": "Steve", "rotation": [90.0, -15.0] }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "rotation": [90.0, -15.0] }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "rotation": [90.0, -15.0]
+ * }
+ *
*/
public class RotationSet {
@@ -38,7 +46,8 @@ private RotationSet() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("rotation/set",
+ namespace.method(
+ "rotation/set",
RotationSetRequest.SCHEMA,
RotationResponse.SCHEMA,
"Sets the rotation of any loaded entity, preserving its position and dimension",
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationSetRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationSetRequest.java
similarity index 83%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationSetRequest.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationSetRequest.java
index 21d11d9..67203e3 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/rotation/RotationSetRequest.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/rotation/RotationSetRequest.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.rotation;
+package dev.loat.msmp_entity.msmp.endpoints.rotation;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -14,12 +14,15 @@
* Request payload for the {@code entity:rotation/set} method.
*
* Example JSON representation:
- *{@code
- * { "name": "Steve", "rotation": [90.0, -15.0] }
- * }
+ *
+ * {
+ * "name": "Steve",
+ * "rotation": [90.0, -15.0]
+ * }
+ *
*
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
* @param rotation The target rotation as {@code [yaw, pitch]}
*/
public record RotationSetRequest(
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/Saturation.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/Saturation.java
similarity index 81%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/Saturation.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/Saturation.java
index 2e3af0c..a9e62ae 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/Saturation.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/Saturation.java
@@ -1,9 +1,10 @@
-package dev.loat.msmp_entity.msmp.methods.saturation;
+package dev.loat.msmp_entity.msmp.endpoints.saturation;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
import dev.loat.msmp_entity.msmp.components.EntityRequest;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+
import net.minecraft.world.entity.player.Player;
@@ -13,15 +14,23 @@
* Returns the current food level and saturation of an online player.
* *Example request:
- *{@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:saturation",
- * "params": [{ "name": "Steve" }] }
- * }
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:saturation",
+ * "params": [{ "name": "Steve" }]
+ * }
+ *
*
* Example response:
- *{@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "food": 18, "saturation": 5.0 }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "food": 18,
+ * "saturation": 5.0
+ * }
+ *
*/
public class Saturation {
@@ -37,7 +46,8 @@ private Saturation() {}
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("saturation",
+ namespace.method(
+ "saturation",
EntityRequest.SCHEMA,
SaturationResponse.SCHEMA,
"Returns the current food level and saturation of an online player",
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationResponse.java
similarity index 81%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationResponse.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationResponse.java
index 580a111..b9ab86b 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationResponse.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationResponse.java
@@ -1,9 +1,10 @@
-package dev.loat.msmp_entity.msmp.methods.saturation;
+package dev.loat.msmp_entity.msmp.endpoints.saturation;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.loat.msmp_entity.msmp.components.EntityRef;
+
import net.minecraft.server.jsonrpc.api.Schema;
@@ -11,16 +12,16 @@
* Response payload shared between {@code entity:saturation} and {@code entity:saturation/set}.
*
* Example JSON representation:
- *{@code
+ *
* {
- * "entity": { "id": "069a...", "name": "Steve" },
- * "food": 18,
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "food": 18,
* "saturation": 5.0
* }
* }
*
- * @param entity The entity reference; always includes UUID and name (players only)
- * @param food The player's current food level (0–20)
+ * @param entity The entity reference; always includes UUID and name (players only)
+ * @param food The player's current food level (0–20)
* @param saturation The player's current saturation level (0.0–20.0)
*/
public record SaturationResponse(EntityRef entity, int food, double saturation) {
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSet.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSet.java
similarity index 79%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSet.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSet.java
index 562429e..7871b4c 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSet.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSet.java
@@ -1,8 +1,9 @@
-package dev.loat.msmp_entity.msmp.methods.saturation;
+package dev.loat.msmp_entity.msmp.endpoints.saturation;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
import dev.loat.msmp_entity.msmp.components.EntityResolver;
+
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
@@ -15,24 +16,40 @@
* Returns the actual values after the update.
*
* Example requests:
- * {@code
+ *
* // Set only food:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:saturation/set",
- * "params": [{ "name": "Steve", "food": 20 }] }
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:saturation/set",
+ * "params": [{ "name": "Steve", "food": 20 }]
+ * }
*
* // Set only saturation:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:saturation/set",
- * "params": [{ "name": "Steve", "saturation": 10.0 }] }
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:saturation/set",
+ * "params": [{ "name": "Steve", "saturation": 10.0 }]
+ * }
*
* // Set both:
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:saturation/set",
- * "params": [{ "name": "Steve", "food": 20, "saturation": 10.0 }] }
- * }
+ * {
+ * "jsonrpc": "2.0",
+ * "id": 1,
+ * "method": "entity:saturation/set",
+ * "params": [{ "name": "Steve", "food": 20, "saturation": 10.0 }]
+ * }
+ *
*
* Example response:
- * {@code
- * { "entity": { "id": "069a...", "name": "Steve" }, "food": 20, "saturation": 10.0 }
- * }
+ *
+ * {
+ * "entity": { "id": "069a...", "name": "Steve" },
+ * "food": 20,
+ * "saturation": 10.0
+ * }
+ *
*/
public class SaturationSet {
@@ -44,13 +61,11 @@ private SaturationSet() {}
* Food level is clamped to 0–20 by Minecraft internally.
* Saturation is clamped to {@code 0.0–foodLevel} by Minecraft internally.
*
- * Throws {@link IllegalArgumentException} if neither {@code food} nor
- * {@code saturation} is provided.
- *
* @param namespace The namespace to register this method under
*/
public static void register(MSMPNamespace namespace) {
- namespace.method("saturation/set",
+ namespace.method(
+ "saturation/set",
SaturationSetRequest.SCHEMA,
SaturationResponse.SCHEMA,
"Partially updates the food level and/or saturation of an online player",
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSetRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSetRequest.java
similarity index 85%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSetRequest.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSetRequest.java
index a89086c..4ccc19b 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/saturation/SaturationSetRequest.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/saturation/SaturationSetRequest.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.saturation;
+package dev.loat.msmp_entity.msmp.endpoints.saturation;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@@ -16,15 +16,15 @@
* Only the provided fields are updated; omitted fields remain unchanged.
*
* Example JSON representations:
- * {@code
+ *
* { "name": "Steve", "food": 20 }
* { "name": "Steve", "saturation": 10.0 }
* { "name": "Steve", "food": 20, "saturation": 10.0 }
- * }
+ *
*
- * @param id The entity's UUID as a string, if provided
- * @param name The player's in-game name, if provided (only works for online players)
- * @param food The new food level to set (0–20), if provided
+ * @param id The entity's UUID as a string, if provided
+ * @param name The player's in-game name, if provided (only works for online players)
+ * @param food The new food level to set (0–20), if provided
* @param saturation The new saturation level to set (0.0–20.0), if provided
*/
public record SaturationSetRequest(
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUID.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUID.java
similarity index 89%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUID.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUID.java
index 5b7e69f..924bfb9 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUID.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUID.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.uuid;
+package dev.loat.msmp_entity.msmp.endpoints.uuid;
import dev.loat.msmp.MSMPNamespace;
import dev.loat.msmp_entity.logging.Logger;
@@ -13,18 +13,23 @@
* which always includes the UUID and the confirmed in-game name.
*
* Example request:
- * {@code
- * { "jsonrpc": "2.0", "id": 1, "method": "entity:uuid",
- * "params": [{ "name": "Steve" }] }
+ *
+ * {@code {
+ * "jsonrpc": "2.0", "id": 1, "method": "entity:uuid",
+ * "params": [{ "name": "Steve" }]
+ * }
* }
*
* Example response:
- * {@code
+ *
+ * {@code
* { "id": "069a79f4-44e9-4726-a5be-fca90e38aaf5", "name": "Steve" }
* }
*/
public class UUID {
+ private UUID() {}
+
/**
* Registers the {@code entity:uuid} method on the given {@link MSMPNamespace}.
*
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUIDRequest.java b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUIDRequest.java
similarity index 94%
rename from src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUIDRequest.java
rename to src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUIDRequest.java
index c050968..76d094e 100644
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/uuid/UUIDRequest.java
+++ b/src/main/java/dev/loat/msmp_entity/msmp/endpoints/uuid/UUIDRequest.java
@@ -1,4 +1,4 @@
-package dev.loat.msmp_entity.msmp.methods.uuid;
+package dev.loat.msmp_entity.msmp.endpoints.uuid;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/Methods.java b/src/main/java/dev/loat/msmp_entity/msmp/methods/Methods.java
deleted file mode 100644
index 7915977..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/Methods.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package dev.loat.msmp_entity.msmp.methods;
-
-import dev.loat.msmp.MSMPNamespace;
-import dev.loat.msmp_entity.msmp.methods.dimension.Dimension;
-import dev.loat.msmp_entity.msmp.methods.dimension.DimensionSet;
-import dev.loat.msmp_entity.msmp.methods.dimension.subscribe.DimensionSubscribe;
-import dev.loat.msmp_entity.msmp.methods.dimension.subscribe.DimensionUnsubscribe;
-import dev.loat.msmp_entity.msmp.methods.health.Health;
-import dev.loat.msmp_entity.msmp.methods.health.HealthSet;
-import dev.loat.msmp_entity.msmp.methods.inventory.Inventory;
-import dev.loat.msmp_entity.msmp.methods.inventory.InventorySet;
-import dev.loat.msmp_entity.msmp.methods.position.Position;
-import dev.loat.msmp_entity.msmp.methods.position.PositionSet;
-import dev.loat.msmp_entity.msmp.methods.rotation.Rotation;
-import dev.loat.msmp_entity.msmp.methods.rotation.RotationSet;
-import dev.loat.msmp_entity.msmp.methods.saturation.Saturation;
-import dev.loat.msmp_entity.msmp.methods.saturation.SaturationSet;
-import dev.loat.msmp_entity.msmp.methods.uuid.UUID;
-
-
-/**
- * Central registration point for all {@code entity} MSMP methods.
- *
- * Each method is implemented in its own sub-package and registered here.
- * Call {@link #register(MSMPNamespace)} once during mod initialization, before
- * the server starts.
- */
-public class Methods {
-
- private Methods() {}
-
- /**
- * Registers all {@code entity} methods on the given {@link MSMPNamespace}.
- *
- * @param namespace The namespace to register all methods under
- */
- public static void register(MSMPNamespace namespace) {
- Dimension.register(namespace);
- DimensionSet.register(namespace);
- DimensionSubscribe.register(namespace);
- DimensionUnsubscribe.register(namespace);
- Health.register(namespace);
- HealthSet.register(namespace);
- Inventory.register(namespace);
- InventorySet.register(namespace);
- Position.register(namespace);
- PositionSet.register(namespace);
- Rotation.register(namespace);
- RotationSet.register(namespace);
- Saturation.register(namespace);
- SaturationSet.register(namespace);
- UUID.register(namespace);
- }
-}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionSubscribe.java b/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionSubscribe.java
deleted file mode 100644
index 24a3023..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionSubscribe.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package dev.loat.msmp_entity.msmp.methods.dimension.subscribe;
-
-import dev.loat.msmp.MSMPNamespace;
-import dev.loat.msmp_entity.logging.RPCConnectionLogger;
-import dev.loat.msmp_entity.msmp.components.EntityRef;
-import dev.loat.msmp_entity.msmp.components.EntityRequest;
-import dev.loat.msmp_entity.msmp.components.EntityResolver;
-import dev.loat.msmp_entity.msmp.subscription.SubscribeRequest;
-import dev.loat.msmp_entity.msmp.subscription.SubscribeResponse;
-import dev.loat.msmp_entity.msmp.subscription.SubscriptionManager;
-import net.minecraft.world.entity.Entity;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-public class DimensionSubscribe {
-
- public static void register(MSMPNamespace namespace) {
- namespace.method("dimension/subscribe",
- SubscribeRequest.SCHEMA,
- SubscribeResponse.SCHEMA,
- "Subscribe to dimension change notifications for the given entities",
- (server, params, client) -> {
- if (params.entities().isEmpty()) {
- return new SubscribeResponse(List.of());
- }
-
- SubscriptionManager manager = SubscriptionManager.get("entity:dimension/subscribe");
- Set uuids = new HashSet<>();
- List resolved = new ArrayList<>();
-
- for (EntityRequest entry : params.entities()) {
- try {
- Entity entity = EntityResolver.resolveEntity(server, entry);
- uuids.add(entity.getUUID());
- resolved.add(EntityResolver.toEntityRef(entity));
- } catch (IllegalArgumentException e) {
- RPCConnectionLogger.warning(client.connectionId(), "entity:dimension/subscribe - " + e.getMessage());
- throw e;
- }
- }
-
- manager.subscribe(uuids);
- RPCConnectionLogger.info(client.connectionId(), "entity:dimension/subscribe - subscribed to %s".formatted(uuids));
- return new SubscribeResponse(resolved);
- }
- );
- }
-}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionUnsubscribe.java b/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionUnsubscribe.java
deleted file mode 100644
index 3d5c4cd..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/dimension/subscribe/DimensionUnsubscribe.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package dev.loat.msmp_entity.msmp.methods.dimension.subscribe;
-
-import dev.loat.msmp.MSMPNamespace;
-import dev.loat.msmp_entity.logging.RPCConnectionLogger;
-import dev.loat.msmp_entity.msmp.components.EntityRef;
-import dev.loat.msmp_entity.msmp.components.EntityRequest;
-import dev.loat.msmp_entity.msmp.components.EntityResolver;
-import dev.loat.msmp_entity.msmp.subscription.SubscribeRequest;
-import dev.loat.msmp_entity.msmp.subscription.SubscribeResponse;
-import dev.loat.msmp_entity.msmp.subscription.SubscriptionManager;
-import net.minecraft.world.entity.Entity;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-public class DimensionUnsubscribe {
-
- public static void register(MSMPNamespace namespace) {
- namespace.method("dimension/unsubscribe",
- SubscribeRequest.SCHEMA,
- SubscribeResponse.SCHEMA,
- "Unsubscribe from dimension change notifications for the given entities",
- (server, params, client) -> {
- if (params.entities().isEmpty()) {
- return new SubscribeResponse(List.of());
- }
-
- SubscriptionManager manager = SubscriptionManager.get("entity:dimension/subscribe");
- Set uuids = new HashSet<>();
- List resolved = new ArrayList<>();
-
- for (EntityRequest entry : params.entities()) {
- try {
- Entity entity = EntityResolver.resolveEntity(server, entry);
- uuids.add(entity.getUUID());
- resolved.add(EntityResolver.toEntityRef(entity));
- } catch (IllegalArgumentException e) {
- RPCConnectionLogger.warning(client.connectionId(), "entity:dimension/unsubscribe - " + e.getMessage());
- throw e;
- }
- }
-
- manager.unsubscribe(uuids);
- RPCConnectionLogger.info(client.connectionId(), "entity:dimension/unsubscribe - unsubscribed from %s".formatted(uuids));
- return new SubscribeResponse(resolved);
- }
- );
- }
-}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventoryResponse.java b/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventoryResponse.java
deleted file mode 100644
index 9c564e2..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/methods/inventory/InventoryResponse.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package dev.loat.msmp_entity.msmp.methods.inventory;
-
-import com.google.gson.JsonElement;
-import com.mojang.serialization.Codec;
-import com.mojang.serialization.Dynamic;
-import com.mojang.serialization.JsonOps;
-import com.mojang.serialization.codecs.RecordCodecBuilder;
-
-import dev.loat.msmp_entity.msmp.components.EntityRef;
-import net.minecraft.server.jsonrpc.api.Schema;
-
-
-/**
- * Response payload shared between {@code entity:inventory} and {@code entity:inventory/set}.
- *
- * The {@code inventory} field mirrors the Vanilla NBT {@code Inventory} format exactly —
- * each entry contains {@code Slot}, {@code id}, {@code count}, and optionally {@code components}.
- *
- * Example JSON representation:
- * {@code
- * {
- * "entity": { "id": "069a...", "name": "Steve" },
- * "inventory": [
- * { "Slot": 0, "id": "minecraft:diamond_sword", "count": 1, "components": { ... } },
- * { "Slot": 36, "id": "minecraft:iron_boots", "count": 1 }
- * ]
- * }
- * }
- *
- * @param entity The entity reference; always includes UUID, name only for players
- * @param inventory The occupied inventory slots in Vanilla NBT format
- */
-public record InventoryResponse(EntityRef entity, JsonElement inventory) {
-
- /**
- * Codec for passing {@link JsonElement} through the serialization pipeline without modification.
- */
- public static final Codec JSON_ELEMENT_CODEC = Codec.PASSTHROUGH.xmap(
- dynamic -> dynamic.convert(JsonOps.INSTANCE).getValue(),
- json -> new Dynamic<>(JsonOps.INSTANCE, json)
- );
-
- private static final Schema INVENTORY_SCHEMA =
- Schema.ofType("array", JSON_ELEMENT_CODEC);
-
- /**
- * Codec for serializing and deserializing {@link InventoryResponse} instances.
- */
- public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group(
- EntityRef.CODEC.fieldOf("entity").forGetter(InventoryResponse::entity),
- JSON_ELEMENT_CODEC.fieldOf("inventory").forGetter(InventoryResponse::inventory)
- ).apply(i, InventoryResponse::new));
-
- /**
- * MSMP schema for {@link InventoryResponse}, used for protocol discovery.
- */
- public static final Schema SCHEMA = Schema.record(CODEC)
- .withField("entity", EntityRef.SCHEMA)
- .withField("inventory", INVENTORY_SCHEMA);
-}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/notifications/Notifications.java b/src/main/java/dev/loat/msmp_entity/msmp/notifications/Notifications.java
deleted file mode 100644
index 4196fb3..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/notifications/Notifications.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package dev.loat.msmp_entity.msmp.notifications;
-
-import dev.loat.msmp.MSMPNamespace;
-import dev.loat.msmp.MSMPServer;
-import dev.loat.msmp_entity.msmp.notifications.dimension.changed.DimensionChanged;
-
-
-/**
- * Central registration point for all {@code entity} MSMP notifications.
- *
- * Each notification is implemented in its own sub-package and registered here.
- * Call {@link #register(MSMPNamespace, DimensionChanged.MSMPServerSupplier)} once
- * during mod initialization, before the server starts.
- *
- * Registered notifications:
- *
- * - {@code entity:notification/dimension/changed} — Fired when an entity changes dimension
- *
- */
-public class Notifications {
-
- private Notifications() {}
-
- /**
- * Registers all {@code entity} notifications and their subscribe/unsubscribe
- * methods on the given {@link MSMPNamespace}.
- *
- * @param namespace The namespace to register all notifications under
- * @param msmpServer Supplier of the current {@link MSMPServer} instance
- */
- public static void register(
- MSMPNamespace namespace,
- DimensionChanged.MSMPServerSupplier msmpServer
- ) {
- DimensionChanged.register(namespace, msmpServer);
- }
-}
diff --git a/src/main/java/dev/loat/msmp_entity/msmp/notifications/dimension/changed/DimensionChanged.java b/src/main/java/dev/loat/msmp_entity/msmp/notifications/dimension/changed/DimensionChanged.java
deleted file mode 100644
index 8ba1e38..0000000
--- a/src/main/java/dev/loat/msmp_entity/msmp/notifications/dimension/changed/DimensionChanged.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package dev.loat.msmp_entity.msmp.notifications.dimension.changed;
-
-import dev.loat.msmp.MSMPNamespace;
-import dev.loat.msmp.MSMPNotification;
-import dev.loat.msmp.MSMPServer;
-import dev.loat.msmp_entity.msmp.components.EntityResolver;
-import dev.loat.msmp_entity.msmp.subscription.SubscriptionManager;
-import net.fabricmc.fabric.api.entity.event.v1.ServerEntityLevelChangeEvents;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.world.entity.Entity;
-
-public class DimensionChanged {
-
- public static void register(
- MSMPNamespace namespace,
- MSMPServerSupplier msmpServer
- ) {
- MSMPNotification notification =
- namespace.notification("dimension/changed", DimensionChangedPayload.SCHEMA,
- "Fired when an entity changes dimension");
-
- ServerEntityLevelChangeEvents.AFTER_ENTITY_CHANGE_LEVEL.register(
- (originalEntity, newEntity, origin, destination) ->
- dispatch(msmpServer, notification, newEntity, origin, destination)
- );
-
- ServerEntityLevelChangeEvents.AFTER_PLAYER_CHANGE_LEVEL.register(
- (player, origin, destination) ->
- dispatch(msmpServer, notification, player, origin, destination)
- );
- }
-
- private static void dispatch(
- MSMPServerSupplier msmpServer,
- MSMPNotification notification,
- Entity entity,
- ServerLevel origin,
- ServerLevel destination
- ) {
- MSMPServer server = msmpServer.get();
- if (server == null) return;
-
- SubscriptionManager manager = SubscriptionManager.get("entity:dimension/subscribe");
- if (!manager.isSubscribed(entity.getUUID())) return;
-
- DimensionChangedPayload payload = new DimensionChangedPayload(
- EntityResolver.toEntityRef(entity),
- origin.dimension().identifier().toString(),
- destination.dimension().identifier().toString()
- );
-
- server.send(notification, payload);
- }
-
- @FunctionalInterface
- public interface MSMPServerSupplier {
- MSMPServer get();
- }
-}
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 104f0f7..da3dd08 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -3,7 +3,7 @@
"id": "msmp-data",
"version": "${version}",
"name": "MSMP Entity",
- "description": "Extends the Minecraft Server Management Protocol (MSMP) by providing additional functions for querying and setting entity data",
+ "description": "Extends the Minecraft Server Management Protocol (MSMP) by providing additional functions for getting and setting entity data",
"authors": [],
"contact": {},
"license": "LGPL-3.0-only",
@@ -24,7 +24,7 @@
"custom": {
"mc-publish": {
"modrinth": {
- "project_id": "---",
+ "project_id": "KoGT0iGr",
"loaders": [
"fabric"
]