From d6a49a2451c6e813d79cd965196dd0ec325444cc Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Sat, 15 Aug 2026 18:41:36 +0200 Subject: [PATCH] add entity attributes --- v0.1/attributes.wit | 56 +++++++++++ v0.1/player.wit | 236 ++++++++++++++++++++++++++++++++++++++++++-- v0.1/plugin.wit | 4 +- v0.1/server.wit | 120 +++++++++++++++++++++- v0.1/world.wit | 42 ++++++++ 5 files changed, 450 insertions(+), 8 deletions(-) create mode 100644 v0.1/attributes.wit diff --git a/v0.1/attributes.wit b/v0.1/attributes.wit new file mode 100644 index 0000000..7481d3a --- /dev/null +++ b/v0.1/attributes.wit @@ -0,0 +1,56 @@ +package pumpkin:plugin@0.1.0; + +interface attributes { + enum attribute { + air-drag-modifier, + armor, + armor-toughness, + attack-damage, + attack-knockback, + attack-speed, + below-name-distance, + block-break-speed, + block-interaction-range, + bounciness, + burning-time, + camera-distance, + explosion-knockback-resistance, + entity-interaction-range, + fall-damage-multiplier, + flying-speed, + follow-range, + friction-modifier, + gravity, + jump-strength, + knockback-resistance, + luck, + max-absorption, + max-health, + mining-efficiency, + movement-efficiency, + movement-speed, + name-tag-distance, + oxygen-bonus, + safe-fall-distance, + scale, + sneaking-speed, + spawn-reinforcements, + step-height, + submerged-mining-speed, + sweeping-damage-ratio, + tempt-range, + water-movement-efficiency, + waypoint-transmit-range, + waypoint-receive-range, + } + enum modifier-operation { + add, + multiply-base, + multiply-total, + } + record attribute-modifier { + id: string, + amount: f64, + operation: modifier-operation, + } +} diff --git a/v0.1/player.wit b/v0.1/player.wit index 9281677..18ad39e 100644 --- a/v0.1/player.wit +++ b/v0.1/player.wit @@ -561,6 +561,226 @@ interface player { is-trusted-skin: bool, } + /// Protocol-level disconnect reasons for Minecraft Bedrock Edition. + enum bedrock-disconnect-reason { + unknown, + cant-connect-no-internet, + no-permissions, + unrecoverable-error, + third-party-blocked, + third-party-no-internet, + third-party-bad-ip, + third-party-no-server-or-server-locked, + version-mismatch, + skin-issue, + invite-session-not-found, + edu-level-settings-missing, + local-server-not-found, + legacy-disconnect, + user-leave-game-attempted, + platform-locked-skins-error, + realms-world-unassigned, + realms-server-cant-connect, + realms-server-hidden, + realms-server-disabled-beta, + realms-server-disabled, + cross-platform-disabled, + cant-connect, + session-not-found, + client-settings-incompatible-with-server, + server-full, + invalid-platform-skin, + edition-version-mismatch, + edition-mismatch, + level-newer-than-exe-version, + no-fail-occurred, + banned-skin, + timeout, + server-not-found, + outdated-server, + outdated-client, + no-premium-platform, + multiplayer-disabled, + no-wifi, + world-corruption, + no-reason, + disconnected, + invalid-player, + logged-in-other-location, + server-id-conflict, + not-allowed, + not-authenticated, + invalid-tenant, + unknown-packet, + unexpected-packet, + invalid-command-request-packet, + host-suspended, + login-packet-no-request, + login-packet-no-cert, + missing-client, + kicked, + kicked-for-exploit, + kicked-for-idle, + resource-pack-problem, + incompatible-pack, + out-of-storage, + invalid-level, + disconnect-packet, + block-mismatch, + invalid-heights, + invalid-widths, + connection-lost, + zombie-connection, + shutdown, + reason-not-set, + loading-state-timeout, + resource-pack-loading-failed, + searching-for-session-loading-screen-failed, + nether-net-protocol-version, + subsystem-status-error, + empty-auth-from-discovery, + empty-url-from-discovery, + expired-auth-from-discovery, + unknown-signal-service-sign-in-failure, + xbl-join-lobby-failure, + unspecified-client-instance-disconnection, + nether-net-session-not-found, + nether-net-create-peer-connection, + nether-net-ice, + nether-net-connect-request, + nether-net-connect-response, + nether-net-negotiation-timeout, + nether-net-inactivity-timeout, + stale-connection-being-replaced, + realms-session-not-found, + bad-packet, + nether-net-failed-to-create-offer, + nether-net-failed-to-create-answer, + nether-net-failed-to-set-local-description, + nether-net-failed-to-set-remote-description, + nether-net-negotiation-timeout-waiting-for-response, + nether-net-negotiation-timeout-waiting-for-accept, + nether-net-incoming-connection-ignored, + nether-net-signaling-parsing-failure, + nether-net-signaling-unknown-error, + nether-net-signaling-unicast-delivery-failed, + nether-net-signaling-broadcast-delivery-failed, + nether-net-signaling-generic-delivery-failed, + editor-mismatch-editor-world, + editor-mismatch-vanilla-world, + world-transfer-not-primary-client, + request-server-shutdown, + client-game-setup-cancelled, + client-game-setup-failed, + no-venue, + nether-net-signaling-signin-failed, + session-access-denied, + service-signin-issue, + nether-net-no-signaling-channel, + nether-net-not-logged-in, + nether-net-client-signaling-error, + sub-client-login-disabled, + deep-link-trying-to-open-demo-world-while-signed-in, + async-join-task-denied, + realms-timeline-required, + guest-without-host, + failed-to-join-experience, + nether-net-data-channel-closed, + discovery-environment-mismatch, + host-without-keys, + host-signed-out, + script-watchdog-exception, + script-memory-limit-exceeded, + storage-low-during-gameplay, + storage-full-during-gameplay, + level-storage-corruption, + edition-mismatch-vanilla-to-edu, + edition-mismatch-edu-to-vanilla, + editor-mismatch-editor-to-vanilla, + editor-mismatch-vanilla-to-editor, + deny-listed, + nonce-missing, + nonce-not-found, + nonce-expired, + nonce-not-valid, + host-disconnected, + editor-join-intent-policy-failure, + nether-net-identity-not-allowed, + invalid-name, + expired-token, + host-accepts-no-type-of-auth, + not-authenticated-fast-fail, + editor-not-allowed, + } + + /// Policy for tearing down the player's network connection. + enum socket-teardown-policy { + /// Send the disconnect packet and gracefully close the connection. + graceful, + /// Send the disconnect packet and close the socket immediately. + immediate-close, + /// Terminate the connection immediately without sending any disconnect packet. + drop-connection, + } + + /// Options for disconnecting a Java Edition player. + record java-kick-options { + /// The formatted text component displayed on the Java disconnect screen. + reason: text-component, + /// Whether to log the kick in the server console (default: true). + log-to-console: bool, + /// How the connection is closed (default: graceful). + teardown-policy: socket-teardown-policy, + } + + /// Options for disconnecting a Bedrock Edition player. + record bedrock-kick-options { + /// Protocol level disconnect code (default: kicked). + reason: bedrock-disconnect-reason, + /// Message displayed on the Bedrock disconnect screen (default: ""). + message: string, + /// Whether to suppress the disconnect message on the client screen (default: false). + skip-message: bool, + /// Filtered message string for safety/parental filters (default: ""). + filtered-message: string, + /// Whether to log the kick in the server console (default: true). + log-to-console: bool, + /// How the connection is closed (default: graceful). + teardown-policy: socket-teardown-policy, + } + + /// Options for banning a player. + record ban-player-options { + /// Ban reason displayed to the player and stored in the ban list. + reason: option, + /// Source or authority responsible for the ban (default: "Plugin"). + source: option, + /// Ban expiration in RFC-3339 format, if temporary. + expires-at-utc: option, + /// Ban duration in seconds from now, if temporary. + duration-seconds: option, + /// Whether to immediately kick the player if currently online (default: true). + kick-if-online: bool, + /// Whether to log the ban action to the server console (default: true). + log-to-console: bool, + } + + /// Options for banning an IP address. + record ban-ip-options { + /// Ban reason stored in the IP ban list. + reason: option, + /// Source or authority responsible for the ban (default: "Plugin"). + source: option, + /// Ban expiration in RFC-3339 format, if temporary. + expires-at-utc: option, + /// Ban duration in seconds from now, if temporary. + duration-seconds: option, + /// Whether to immediately kick all online players with this IP (default: true). + kick-matching-players: bool, + /// Whether to log the IP ban action to the server console (default: true). + log-to-console: bool, + } + /// A handle to a player on the server. resource player { /// Returns the player as an entity. @@ -642,18 +862,16 @@ interface player { teleport: func (position: position, yaw: option, pitch: option, %world: %world); /// Teleports the player to another world at a specific position. teleport-world: func (world-ref: %world, position: position, yaw: option, pitch: option); - /// Kicks the player from the server with the specified reason. - kick: func (message: text-component); /// Forces the player to respawn. respawn: func (); /// Opens a GUI for the player. open-gui: func (gui-ref: gui); - /// Bans the player with an optional reason. - ban: func (reason: option); - /// Bans the player's IP address with an optional reason. - ban-ip: func (reason: option); + /// Bans the player with the specified options. + ban: func (options: ban-player-options); + /// Bans the player's IP address with the specified options. + ban-ip: func (options: ban-ip-options); /// Transfers the player to another server. transfer: func (host: string, port: u16); @@ -946,6 +1164,9 @@ interface player { /// Clears all custom resource packs for the Java player. clear-resource-packs: func(); + + /// Kicks the Java player with the specified options. + kick: func(options: java-kick-options); } /// A handle to a player connected via the Bedrock Edition. @@ -987,6 +1208,9 @@ interface player { /// Sends resource packs information to the Bedrock player. send-resource-packs-info: func(info: bedrock-resource-packs-info); + + /// Kicks the Bedrock player with the specified options. + kick: func(options: bedrock-kick-options); } /// Returns a list of all players in a specific world. diff --git a/v0.1/plugin.wit b/v0.1/plugin.wit index ffd875d..194e527 100644 --- a/v0.1/plugin.wit +++ b/v0.1/plugin.wit @@ -45,8 +45,10 @@ world plugin { import status-effect; /// Provides block entity types and instances. import block-entity; - // Provides 1 : 1 inter-plugin communication + /// Provides 1 : 1 inter-plugin communication import ipc; + /// Provides entity attribute types and modifiers. + import attributes; /// Provides player management. import player; diff --git a/v0.1/server.wit b/v0.1/server.wit index 80d6efd..a44408c 100644 --- a/v0.1/server.wit +++ b/v0.1/server.wit @@ -1,10 +1,119 @@ interface server { - use player.{player}; + use player.{player, ban-player-options, ban-ip-options}; use common.{game-mode}; use %world.{%world}; use text.{text-component}; use uuid.{uuid}; use recipe.{recipe-manager}; + use permission.{permission-level}; + + /// Represents an operator entry in the ops configuration. + record op-entry { + uuid: uuid, + name: string, + level: permission-level, + bypasses-player-limit: bool, + } + + /// Interface for querying and managing server operators. + resource op-manager { + /// Checks if a player UUID is currently an operator. + is-op: func(id: uuid) -> bool; + + /// Retrieves the operator entry for a player UUID, if present. + get-op: func(id: uuid) -> option; + + /// Gets the effective permission level for a player UUID (returns zero if not op). + get-permission-level: func(id: uuid) -> permission-level; + + /// Grants operator status to a player (online or offline) with the specified level and bypass setting. + op-player: func(name: string, id: uuid, level: permission-level, bypasses-player-limit: bool); + + /// Revokes operator status from a player (online or offline). Returns true if the player was previously op. + deop-player: func(id: uuid) -> bool; + + /// Returns a list of all operator entries on the server. + list-ops: func() -> list; + } + + /// Represents a banned player entry in the ban list. + record banned-player-entry { + uuid: uuid, + name: string, + created: string, + source: string, + expires: option, + reason: string, + } + + /// Represents a banned IP entry in the IP ban list. + record banned-ip-entry { + ip: string, + created: string, + source: string, + expires: option, + reason: string, + } + + /// Global manager for player and IP bans. + resource ban-manager { + /// Checks if a player UUID is currently banned. + is-player-banned: func(id: uuid) -> bool; + + /// Retrieves the ban entry for a player UUID, if banned. + get-player-ban: func(id: uuid) -> option; + + /// Bans a player by name and UUID with the specified options (works for online and offline players). + ban-player: func(name: string, id: uuid, options: ban-player-options); + + /// Removes a player ban by UUID. Returns true if the player was banned. + unban-player: func(id: uuid) -> bool; + + /// Returns all currently active player bans. + list-player-bans: func() -> list; + + /// Checks if an IP address is currently banned. + is-ip-banned: func(ip: string) -> bool; + + /// Retrieves the ban entry for an IP address, if banned. + get-ip-ban: func(ip: string) -> option; + + /// Bans an IP address with the specified options. + ban-ip: func(ip: string, options: ban-ip-options); + + /// Removes an IP ban. Returns true if the IP was banned. + unban-ip: func(ip: string) -> bool; + + /// Returns all currently active IP bans. + list-ip-bans: func() -> list; + } + + /// Represents a player entry in the server whitelist. + record whitelist-entry { + uuid: uuid, + name: string, + } + + /// Global manager for the server whitelist. + resource whitelist-manager { + /// Returns whether the whitelist is currently enabled. + is-enabled: func() -> bool; + + /// Enables or disables the server whitelist. If enabled and enforce-whitelist is set, kicks non-whitelisted players. + set-enabled: func(enabled: bool); + + /// Checks if a player UUID is on the whitelist. + is-whitelisted: func(id: uuid) -> bool; + + /// Adds a player to the whitelist (online or offline). Returns true if newly added. + add-player: func(name: string, id: uuid) -> bool; + + /// Removes a player from the whitelist. Returns true if the player was on the whitelist. + remove-player: func(id: uuid) -> bool; + + /// Returns all whitelisted player entries. + list-entries: func() -> list; + } /// Represents the difficulty setting of a Minecraft server. enum difficulty { @@ -118,5 +227,14 @@ interface server { /// Returns the recipe manager to register custom recipes. get-recipe-manager: func() -> recipe-manager; + + /// Returns the operator manager to query or modify server operators. + get-op-manager: func() -> op-manager; + + /// Returns the global ban manager for querying and modifying player and IP bans. + get-ban-manager: func() -> ban-manager; + + /// Returns the global whitelist manager for querying and modifying the server whitelist. + get-whitelist-manager: func() -> whitelist-manager; } } diff --git a/v0.1/world.wit b/v0.1/world.wit index 8747ece..7682ffd 100644 --- a/v0.1/world.wit +++ b/v0.1/world.wit @@ -7,9 +7,23 @@ interface %world { use sounds.{sound}; use entity-types.{entity-type}; use biomes.{biome}; + use attributes.{attribute, modifier-operation, attribute-modifier}; + use item-stack.{item-stack}; use uuid.{uuid}; + /// Equipment slots available on living entities (mobs, armor stands, players). + enum equipment-slot { + main-hand, + off-hand, + feet, + legs, + chest, + head, + body, + saddle, + } + /// Defines how a block reacts when pushed by a piston. enum piston-behavior { /// Normal behavior; the block can be pushed and pulled. @@ -224,6 +238,34 @@ interface %world { get-absorption: func() -> f32; set-absorption: func(amount: f32); + // Attributes + + /// Returns the computed value of the specified attribute for this entity. + get-attribute-value: func(attr: attribute) -> f64; + /// Returns the base value of the specified attribute for this entity. + get-attribute-base: func(attr: attribute) -> f64; + /// Sets the base value of the specified attribute for this entity. + set-attribute-base: func(attr: attribute, value: f64); + /// Adds or replaces an attribute modifier for the specified attribute. + add-attribute-modifier: func(attr: attribute, modifier: attribute-modifier); + /// Removes an attribute modifier by its identifier. + remove-attribute-modifier: func(attr: attribute, id: string); + /// Returns all attribute modifiers currently attached to the specified attribute. + get-attribute-modifiers: func(attr: attribute) -> list; + /// Resets the specified attribute to its default base value with no modifiers. + reset-attribute: func(attr: attribute); + /// Resets all attributes on this entity to their default base values and removes all modifiers. + reset-all-attributes: func(); + + // Equipment + + /// Gets the item currently equipped in the specified slot, if any. + get-equipment: func(slot: equipment-slot) -> option; + /// Sets the item equipped in the specified slot and broadcasts the change to tracking clients. + set-equipment: func(slot: equipment-slot, stack: option); + /// Clears all equipment on this entity and broadcasts the removal. + clear-equipment: func(); + get-age: func() -> s32; set-age: func(age: s32);