Cosmetic Mod Protocol

Version: 1.0.0
Category: Modding
Scope: Guild Customization


Overview

This protocol defines how AI agents should interact with the cosmetic modding system for Struct Types. Cosmetic mods allow customization of appearance and lore without changing game capabilities.


Protocol Principles

  1. Cosmetic Only: Cosmetics only affect appearance and text, not game mechanics
  2. Separate from Blockchain: Cosmetics are off-chain, not stored in structsd
  3. Distributed System: Each guild maintains their own cosmetics
  4. On-Demand Transfer: Cosmetics are shared peer-to-peer when needed
  5. Caching: Received cosmetics are cached for performance
  6. Hash-Based Identification: Sets and skins use SHA-256 hashes (not IDs) for uniqueness
  7. Class-Based Linking: Skins link to Struct Types via class field (on-chain/database)
  8. Two-Layer Structure: Sets (collections) and Skins (individual cosmetics)
  9. Localization Support: All text supports multiple languages
  10. File-Based: Sets/skins are directory structures (distributed as ZIP)

Set and Skin Structure

Directory Layout

For Sets:

cosmetic-set/
├── set-manifest.json      # Required: Set metadata (with setHash)
├── skins/                 # Required: Individual skins
│   └── {skinHash}/
│       ├── skin-manifest.json
│       ├── struct-type.json
│       └── assets/
└── localizations/         # Optional: Set-level localizations

For Standalone Skins:

cosmetic-skin/
├── skin-manifest.json     # Required: Skin metadata (with skinHash)
├── struct-type.json       # Required: Struct type cosmetic data
├── animations/            # Optional: Lottie JSON files
├── icons/                 # Optional: Icon files
└── graphics/              # Optional: Other graphics

Set Manifest Schema

Location: set-manifest.json
Schema: schemas/cosmetic-set.md

Required Fields:

Optional Fields:

Skin Manifest Schema

Location: skin-manifest.json
Schema: schemas/cosmetic-skin.md

Required Fields:

Optional Fields:


Cosmetic Distribution System

Architecture

The cosmetic system operates separate from the blockchain as a distributed, peer-to-peer network:

Cosmetic Transfer Flow

Scenario: Player from Guild A visits planet of player from Guild B

  1. Detection: Game detects Guild B structs on planet
  2. Cache Check: Guild A checks local cache for Guild B cosmetics
  3. Request (if not cached): Guild A requests cosmetics from Guild B
  4. Transfer: Guild B sends cosmetic mods to Guild A
  5. Cache: Guild A stores received cosmetics in cache
  6. Render: Game renders Guild B structs with their custom appearance
  7. Future Visits: Use cached cosmetics (faster)

Priority Order

  1. Own Guild Cosmetics (if viewing own structs)
  2. Cached Cosmetics (if viewing other guild’s structs - from cache)
  3. Requested Cosmetics (if not cached - request from source guild)
  4. Default game assets (fallback if no cosmetics available)

Request Cosmetics from Another Guild

{
  "action": "requestCosmetics",
  "parameters": {
    "fromGuildId": "0-2",
    "classes": ["Miner", "Reactor"],
    "cachedHashes": {
      "Miner": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
      "Reactor": null
    }
  }
}

Response:

{
  "status": "success",
  "guildId": "0-2",
  "skins": [
    {
      "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
      "class": "Miner",
      "version": "1.0.1",
      "needsUpdate": true,
      "skin": { /* cosmetic skin data */ }
    }
  ],
  "assetUrls": {
    "miner-idle.json": "https://guild-b.example.com/cosmetics/assets/miner-idle.json"
  },
  "cached": false
}

Check Cosmetic Cache

{
  "action": "checkCosmeticCache",
  "parameters": {
    "guildId": "0-2",
    "classes": ["Miner", "Reactor"]
  }
}

Response:

{
  "cached": true,
  "guildId": "0-2",
  "hashes": {
    "Miner": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
    "Reactor": "e1d2c3b4a56789012345678901234567890abcdef1234567890abcdef1234567"
  },
  "cachePath": "~/.structs/guilds/0-1/cosmetics/cache/guild-0-2",
  "expiresAt": "2025-01-16T10:00:00Z"
}

Querying Mods

Get Available Mods

{
  "action": "listCosmeticMods",
  "parameters": {}
}

Response:

{
  "mods": [
    {
      "modId": "guild-alpha-miner-v1",
      "name": {"en": "Guild Alpha Miner Pack"},
      "version": "1.0.0",
      "author": "Guild Alpha",
      "guildId": "0-1",
      "structTypes": ["miner"],
      "languages": ["en", "es"]
    }
  ]
}

Get Set Details

{
  "action": "getCosmeticSet",
  "parameters": {
    "setHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"
  }
}

Response:

{
  "setHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
  "set": { /* full set manifest */ },
  "skins": [ /* skin references */ ]
}

Get Skin Details

{
  "action": "getCosmeticSkin",
  "parameters": {
    "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456"
  }
}

Response:

{
  "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
  "skin": { /* full skin manifest */ }
}

Get Struct Type Cosmetics by Class

{
  "action": "getStructTypeCosmetics",
  "parameters": {
    "class": "Miner",
    "language": "en"
  }
}

Response:

{
  "class": "Miner",
  "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
  "name": "Alpha Extractor",
  "lore": "Guild Alpha's signature mining unit...",
  "weapons": [
    {
      "weaponType": "primary",
      "name": "Plasma Drill",
      "description": "High-powered plasma drilling system"
    }
  ],
  "abilities": [
    {
      "abilityId": "mine",
      "name": "Deep Extraction",
      "description": "Extract resources from planetary deposits"
    }
  ],
  "animations": {
    "idle": "animations/miner-idle.json",
    "active": "animations/miner-mining.json"
  },
  "icon": "icons/miner-alpha.png"
}

Creating Mods

Validate Set/Skin Structure

{
  "action": "validateCosmeticSet",
  "parameters": {
    "setPath": "path/to/set"
  }
}

Response:

{
  "valid": true,
  "setHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
  "errors": [],
  "warnings": [
    "Missing fallback language (en) in localizations"
  ]
}

Validate Skin

{
  "action": "validateCosmeticSkin",
  "parameters": {
    "skinPath": "path/to/skin"
  }
}

Response:

{
  "valid": true,
  "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
  "errors": [],
  "warnings": []
}

Create Set Manifest

{
  "action": "createCosmeticSet",
  "parameters": {
    "name": {"en": "Guild Alpha Mining Set"},
    "version": "1.0.0",
    "author": "Guild Alpha",
    "guildId": "0-1"
  }
}

Response:

{
  "status": "success",
  "setHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
  "setPath": "~/.structs/guilds/0-1/cosmetics/sets/a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
  "manifestPath": "~/.structs/guilds/0-1/cosmetics/sets/a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456/set-manifest.json"
}

Add Skin to Set

{
  "action": "addSkinToSet",
  "parameters": {
    "setHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
    "class": "Miner",
    "cosmetic": {
      "name": {"en": "Alpha Extractor"},
      "lore": {"en": "Guild Alpha's signature mining unit..."},
      "animations": {
        "idle": "miner-idle.json"
      }
    }
  }
}

Response:

{
  "status": "success",
  "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456",
  "skinPath": "~/.structs/guilds/0-1/cosmetics/sets/a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456/skins/f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456"
}

Localization

Language Codes

Use ISO 639-1 language codes:

Fallback

Always provide English (en) as fallback language.

Localization Structure

{
  "en": {
    "miner.description": "Mining unit",
    "miner.weapon.primary": "Drill"
  },
  "es": {
    "miner.description": "Unidad de minería",
    "miner.weapon.primary": "Taladro"
  }
}

Asset Management

Animation Files

Icon Files

Graphics Files


Error Handling

Invalid Hash

{
  "error": "invalid_hash",
  "message": "Hash validation failed",
  "details": {
    "field": "setHash",
    "issue": "Hash mismatch: expected a1b2c3d4..., got f1e2d3c4..."
  }
}

Invalid Hash Format

{
  "error": "invalid_hash_format",
  "message": "Hash format validation failed",
  "details": {
    "field": "skinHash",
    "issue": "Invalid format: must be 64-character hexadecimal string"
  }
}

Missing Struct Type Class

{
  "error": "struct_type_class_not_found",
  "message": "Struct type class not found in game",
  "details": {
    "class": "InvalidClass"
  }
}

Missing Asset

{
  "error": "asset_not_found",
  "message": "Referenced asset file not found",
  "details": {
    "path": "animations/miner-idle.json",
    "skinHash": "f1e2d3c4b5a6789012345678901234567890abcdef1234567890abcdef123456"
  }
}

Best Practices

  1. Always validate mods before distribution
  2. Include fallback language (English) in all mods
  3. Use relative paths for all asset references
  4. Test animations in game before distribution
  5. Version mods using semantic versioning
  6. Document changes in mod description
  7. Optimize assets for performance


Protocol Version: 1.0.0