feat(shared): support server-pushed resource packs
This commit is contained in:
parent
5c61ecc209
commit
339c0efe5a
|
|
@ -1,6 +1,4 @@
|
||||||
//! Network protocol types and constants.
|
//! Network protocol types and constants.
|
||||||
//!
|
|
||||||
//! This module defines the pure, serde-serializable messages used for network communication between the client and server. It contains no networking logic or async dependencies.
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -42,9 +40,9 @@ pub struct HandshakeAck {
|
||||||
pub protocol_version: u32,
|
pub protocol_version: u32,
|
||||||
/// Human-readable server build string.
|
/// Human-readable server build string.
|
||||||
pub server_build: String,
|
pub server_build: String,
|
||||||
/// Packs the world requires, each with an optional download source. Empty in M1.
|
/// Packs the world requires, each with an optional download source. May include `PackTier::Resource` entries (a server resource pack), which are delivered one-way and applied client-side rather than strict-matched; a consumer must branch on tier (or `PackTier::requires_strict_match`) before treating an entry as a match requirement.
|
||||||
pub world_packs: Vec<RequiredPack>,
|
pub world_packs: Vec<RequiredPack>,
|
||||||
/// Packs the client is missing relative to the server, each with an optional download source. Empty in M1.
|
/// Packs the client is missing relative to the server, each with an optional download source. As with `world_packs`, `PackTier::Resource` entries are delivered, not matched.
|
||||||
pub missing_packs: Vec<RequiredPack>,
|
pub missing_packs: Vec<RequiredPack>,
|
||||||
/// Which stream carries which purpose for this session.
|
/// Which stream carries which purpose for this session.
|
||||||
pub stream_layout: StreamLayout,
|
pub stream_layout: StreamLayout,
|
||||||
|
|
@ -77,6 +75,8 @@ pub enum RejectReason {
|
||||||
ProtocolMismatch,
|
ProtocolMismatch,
|
||||||
/// Client is missing required packs or has incompatible versions.
|
/// Client is missing required packs or has incompatible versions.
|
||||||
PackMismatch,
|
PackMismatch,
|
||||||
|
/// Client declined or failed to fetch a server resource pack the server marked required.
|
||||||
|
ResourcePackDeclined,
|
||||||
/// Client failed to authenticate.
|
/// Client failed to authenticate.
|
||||||
AuthFailed,
|
AuthFailed,
|
||||||
/// Client is banned from the server.
|
/// Client is banned from the server.
|
||||||
|
|
@ -96,8 +96,6 @@ pub struct PlayerIdentity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reference to a content pack (resource pack, data pack, or Lua mod) as it appears in a modlist exchanged during the handshake.
|
/// Reference to a content pack (resource pack, data pack, or Lua mod) as it appears in a modlist exchanged during the handshake.
|
||||||
///
|
|
||||||
/// Identity is the pair (`id`, `content_hash`): `id` names the pack and `content_hash` is the authoritative value compared when deciding whether two installations agree. `version` is informational (display, logs, upgrade prompts) and is **not** the match key — two builds sharing a version but differing in contents are distinct packs.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct PackRef {
|
pub struct PackRef {
|
||||||
/// Namespaced content identifier of the pack (`namespace:id`). Charset validation is deferred to the modlist-matching concept (out of M1 scope).
|
/// Namespaced content identifier of the pack (`namespace:id`). Charset validation is deferred to the modlist-matching concept (out of M1 scope).
|
||||||
|
|
@ -114,7 +112,7 @@ pub struct PackRef {
|
||||||
/// Classification of a content pack, determining the handshake matching rule applied to it. Inferred from folder contents, not self-declared: `assets/`-only is a resource pack, `data/`-only is a data pack, presence of `scripts/` is a Lua mod.
|
/// Classification of a content pack, determining the handshake matching rule applied to it. Inferred from folder contents, not self-declared: `assets/`-only is a resource pack, `data/`-only is a data pack, presence of `scripts/` is a Lua mod.
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum PackTier {
|
pub enum PackTier {
|
||||||
/// Client-only asset overlay (`assets/` only). Never streamed by the server, never matched.
|
/// Client-side asset overlay (`assets/` only). Never strict-matched between peers. A server may push one server resource pack of its own, delivered one-way and applied on top of the client's local pack stack; enforcement of a `required` server pack is apply-or-reject at the client, not a peer hash-match.
|
||||||
Resource,
|
Resource,
|
||||||
/// Declarative content (`data/` only). Must match exactly between peers.
|
/// Declarative content (`data/` only). Must match exactly between peers.
|
||||||
Data,
|
Data,
|
||||||
|
|
@ -126,7 +124,7 @@ pub enum PackTier {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PackTier {
|
impl PackTier {
|
||||||
/// Returns whether a pack of this tier must match byte-for-byte between client and server for the connection to be accepted. Resource packs are never matched; data packs and non-`client_only` mods must match exactly (see Load order § modlist matching).
|
/// Returns whether a pack of this tier must match byte-for-byte between client and server for the connection to be accepted. Resource packs are never matched; data packs and non-`client_only` mods must match exactly. A `false` here does not imply the server never sends the pack, a server resource pack is delivered one-way despite not being part of bidirectional matching.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn requires_strict_match(self) -> bool {
|
pub fn requires_strict_match(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -144,6 +142,8 @@ pub struct RequiredPack {
|
||||||
pub pack: PackRef,
|
pub pack: PackRef,
|
||||||
/// Optional HTTP(S) URL to fetch the pack from, bypassing the QUIC asset stream for large downloads. `None` means fetch over the asset stream.
|
/// Optional HTTP(S) URL to fetch the pack from, bypassing the QUIC asset stream for large downloads. `None` means fetch over the asset stream.
|
||||||
pub download_url: Option<String>,
|
pub download_url: Option<String>,
|
||||||
|
/// Whether the connection is rejected if the client cannot obtain and apply this pack. For data/mod tiers this is always `true` (they are mandatory for a correct session). For a `PackTier::Resource` entry (a server resource pack) it distinguishes an *optional* overlay the client may decline and keep playing (`false`) from a *required* one whose decline or fetch failure rejects the connection (`true`).
|
||||||
|
pub required: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optional protocol feature bits.
|
/// Optional protocol feature bits.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ Two distinct, orthogonal systems. They are kept separate and are not collapsed i
|
||||||
|
|
||||||
Client-side asset overlays: textures, sounds, models, fonts, language files. No logic.
|
Client-side asset overlays: textures, sounds, models, fonts, language files. No logic.
|
||||||
|
|
||||||
A pack is a directory tree mirroring `/assets/` that overrides files by path. The renderer/asset loader resolves logical asset IDs against a stack of pack roots (base game → installed packs by priority) and the topmost hit wins. The server has no involvement. Ownership sits with the asset pipeline (in `client`, or a sibling `assets` crate if it grows). Pack authors never touch Lua.
|
A pack is a directory tree mirroring `/assets/` that overrides files by path. The renderer/asset loader resolves logical asset IDs against a stack of pack roots (base game → installed packs by priority) and the topmost hit wins. Ownership sits with the asset pipeline (in `client`, or a sibling `assets` crate if it grows). Pack authors never touch Lua.
|
||||||
|
|
||||||
|
A client's own resource packs are a purely local choice; the server has no say over them and they are never part of gameplay modlist matching. The **one** exception is a **server resource pack**: a server may push a single cosmetic overlay of its own (a themed / total-conversion server) to connecting clients. It is a one-way server → client push, applied on top of the client's local stack, and enforced per the server's choice — *optional* packs the client may decline and keep playing, a *required* pack the client declines or fails to fetch rejects the connection. It is still `assets/`-only (no `data/`, no `scripts/`), so it can never affect authoritative state. Fetch and enforcement semantics live in the vault's `Architecture/Load order.md` § Streaming.
|
||||||
|
|
||||||
## Data packs
|
## Data packs
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue