Skip to content

About

Cyberia MMO World foundation, sagas, procedural generation templates, and versioned content artifacts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

CYBERIA online

cyberia content

The Cyberia content: the foundation, the instances, the sagas, the semantic generator and the versioned content artifact the engine consumes.

This repository creates content. The engine imports, materializes, releases and deploys it.

cyberia-content ──validate──► build ──► dist/ (the content artifact: data and its manifest)
                                              │
            engine: this checkout (CYBERIA_CONTENT_ROOT) or a packed copy of it
                                              │
                cyberia instance --import · content import · content-release

Layout

Path Holds
src/content/foundation/ The functional blueprint: world, environment, items, characters, maps, quests, actions
src/content/instances/ Instance backups, one directory per instance code, as the engine exports it
src/content/global/ Global content: one Object Layer definition per CID that no world carries
src/content/sagas/ Saga packages, one file per saga code
src/content/procedural/ Genesis Templates and global palettes: where a procedural generation starts
src/schema/ The definition schema and the runtime contract (generated by the engine)
src/validation/ Content rules and the canonical JSON form
src/procedural.js Reads the procedural templates and checks them against the foundation
src/compiler.js Definitions to runtime documents: one list per document family
src/generator/ Semantic generation: prompts, stages, the saga package, the Gemini client
src/packaging/ The artifact: build, manifest and digests

CLI

npm install
node bin/cyberia-content.js <command>
Command Does
validate [--fix] Validate canonical form, foundation, sagas and instances; --fix rewrites form
saga generate Compose a saga with Google Gemini and write its package
saga step --state <file> Run the next step of a stored generation and write the state back
saga check --file <file> [--write] Print JSON: the findings of a package, its runtime documents and its context
saga instance <saga-code> [--force] [--dry-run] Write the instance backup of a saga
build Write dist/ from the committed content
pack Build and pack artifacts/cyberia-content-<version>.tgz

--env-file <path> reads the environment from a file. ./.env is read when it exists.

Configuration

cyberia-content.config.js configures this checkout. Every command and test reads it.

Field Holds
ignoreSagas Saga codes every process skips, as if their package does not exist. dist/ omits them

Remove a saga code from ignoreSagas when its package is valid.

The foundation

The foundation defines what exists and how it functions. Studio adds only how it looks (render) and where it is (placement).

A definition id is <kind>.<slug>, for example biome.violet-strata. One JSON file holds one definition, at <category>/<id>.json. Every definition has a name, a description and a role.

Kinds Define
region, biome, faction, origin, material The world. Only the foundation defines them
floor, tree, vegetation, rock, prop, structure, ruin, portal Environment: each one is an Object Layer item and an entity
weapon, armor, skin, projectile, currency, resource, consumable, relic, technology, implant, tool Carried items
character Loadout, carried items, the spawned entity and a greeting
ability, effect What items do: a runtime skill handler and its effects
map A place of one biome, and its composition: each entity and how many
quest Provider, steps, objectives, rewards, talk, prerequisites and unlocks
action What a provider offers: shop, recipes, storage, buyback, burn, market

An item or environment definition carries an objectLayer block: the item type, the activable flag and the stats. Its item label is its slug. Its artBrief tells an artist what to draw. It holds no pixels, frames, atlases or CIDs.

A consumable heals its resistance stat as life and carries no other stat. An ability with the zero-waste-auto-consume-heal logic lets its holder consume one unit by itself, once the missing life takes the whole heal. The ability names no summons: it summons the consumable that carries it, and only a consumable may carry it. Its optional loot names the pickup behavior of the item as world loot (consume-on-pickup-heal); the compiler writes it as a loot entity-type default. Without it, a world pickup of the item grants it.

A biome carries a palette: #rrggbb colors by role (base, shadow, highlight, outline, and optionally accent and special). The Studio paints with it; it is guidance, never render.

A map composes entities its biome holds. The compiled map holds none: Studio places each one and tracks the composition against the context index. A quest provider and each talk target stand behind an action of the same set.

The runtime gates a quest by its prerequisites alone. A quest that unlocks another is one of its prerequisites, a prerequisite of the same set unlocks the quest it gates, and no chain of prerequisites loops. A kill objective targets a character that spawns as a bot.

An action has no type: its capabilities are the fields it fills, and it may combine several. A market terminal names a market of the foundation; the market owns the shared terms. The economy item policy still decides what a buyback, a burn or a listing may take.

foundation.json holds the schemaVersion of the definition format and the baseline: the definition each runtime entity type resolves against when a world authors none (entities), and the item whose activable flag and stats a new item of each type starts from (items).

The procedural templates

The engine generates candidate renders from these templates. They are where a generation starts, never a render, and they define no item.

A Genesis Template, procedural/genesis-templates/<itemType>.<slug>.json, is a reusable visual start for one item type:

Field Holds
canvas Width and height in cells
directions One region map per direction code: one string per row, one letter per cell
legend The region id each letter marks; . marks no region
roles The roles: the regions, the palette role and the shadow, base, highlight tones
outline The outline color
frameDurationMs The frame duration of a render that starts from the template

A role with artDirection takes the colors the art direction of an item names. Each role names the palette role it takes in palette: primary, secondary, detail or feature.

A palette, procedural/palettes/<slug>.json, is one theme of one global library. It belongs to no item type. It gives a color to primary and outline, and to any of secondary, detail, feature and accent the theme needs. Every palette colors every Genesis Template: a role takes the color of its palette role, and a role whose palette role the palette does not give keeps its default. A palette has a unique name, a family, the foundation biomes it suits (biomeTags, by slug) and its constraints: the least OKLab distance between the outline and the contrastRoles. The engine derives the shadow and highlight of each role and checks the contrast.

Palette role Takes Skin Floor Portal Obstacle
primary The main mass torso ground swirl chunk
secondary The second mass legs patch rim loose
detail Small dark parts and lines hair depth seam
feature The distinct part skin core dust

A new item of a type takes its function from baseline.items, its look from a Genesis Template and its colors from a palette. A human then finishes it in the Object Layer Studio.

The compiler

src/compiler.js turns definitions into runtime documents, one list per family, in import order:

Family Documents
object-layers One Object Layer item per labeled definition, without render
entity-type-defaults One per entity definition: live, dead, drop and inventory items, behavior
skills One per item whose abilities name a runtime handler
maps One per map: code, name, description and biome tags; no entities
quests Steps, objectives and rewards by item label; source map and cell null
dialogues Item flavor text, character greetings and quest talk
actions Shop, recipes, storage and quest talk codes; source map and cell null

The same compiler compiles the foundation and each saga. It also derives the context index the Studio reads: every definition of the foundation and the sagas, its source, the item label and the map entity it answers to, and every reference in both directions with the field that makes it.

Semantic generation

The generator composes a saga over the foundation. Gemini reuses foundation definitions and adds only what the saga lacks, in the definition model of the foundation.

theme  (from --prompt, or synthesized from the lore)
   │
   ▼
Google Gemini, six bounded stages, each one returning definitions
   │   1 composition → saga identity, the foundation ids it uses, new definitions
   │   2 maps        → maps of foundation biomes, and what each one composes
   │   3 quests      → quests over characters and items
   │   4 dialogues   → greetings of new characters and the talk of quests
   │   5 actions     → what each quest provider and talk target offers
   │   6 abilities   → abilities of new items, reused or defined
   ▼
normalize → validate → src/content/sagas/<saga-code>.json

The composition stage reads a compact index of the foundation. Each later stage reads the full definitions of what the saga uses. The model follows these rules, and normalization enforces them:

  • Reuse a foundation definition by its exact id. Never define a duplicate.
  • Never define a region, biome, faction, origin or material.
  • Use only the skill handlers of the runtime contract.
  • Write no coordinates, cells, grids, portal endpoints, pixels, frames, atlases or CIDs.

An invalid package is written for a human to fix. The command then fails with its findings.

A generation is a JSON state that each step advances: the theme, each stage, then the package. saga step --state <file> runs the next step and writes the state back; a step that fails leaves the state as it was, and exit code 2 means the request cannot run. A step retries a timeout or a quota answer, after the delay the answer names; a request the model refuses fails at once with exit code 2. The engine stores the state after each step, so a generation resumes where it stopped. The request of a state may fix the saga identity (saga), name definitions the saga must use (reuse) and name the sagas whose definitions it may reuse (sagas).

saga check --file <file> checks a package as validate would after it is written, against the foundation and every other saga. It prints JSON: findings, and for a valid package compiled (the runtime documents of the saga) and context (the context index entries of its definitions, of what they name and of what names them). --write writes a valid package to its file in canonical form.

# A lore-grounded saga. The world foundation is the lore unless --lore-path names a document.
node bin/cyberia-content.js saga generate

# A given theme, validated but not written
node bin/cyberia-content.js saga generate --prompt "A relay keeper in the ash wastes" --dry-run

GEMINI_API_KEY must be in the environment. Steer a synthesized theme with --space-context (physical, mixed, hyperspace), --tone (adventure, politics, tragic, comedy), --faction-context (foundation confederations that drive the saga, for example nova,zenith), --character-context (name pools) and --cultural-exposure (cosmopolitan, local).

The saga package

Field Holds
schemaVersion Version of the package format
foundationVersion The content version the saga was composed against
saga code, name, description
references Every id of the foundation or of another saga the definitions name
places Optional: the maps of the foundation or of another saga it plays on
definitions The new definitions, maps, quests and actions, in the foundation model

The build compiles a package with the compiler of the foundation. The saga adds its own documents of every family, its CyberiaSaga record and the shell of its instance.

A saga may use a definition of another saga by its id, as it uses a foundation one. It never defines it again: the saga that defines it compiles its documents. An id or an item label belongs to one source only.

A place is a map the saga uses and another source defines. The CyberiaSaga record names its own maps in mapCodes and its places in placeCodes. The source that defines a place stays its owner: the saga compiles no document of it, and its instance shell does not hold it. A quest or an action whose provider stands on a place gets that map as its source map. Each place names a map of another source, once.

The instance of a saga

saga instance <saga-code> writes src/content/instances/<saga-code>/ from the saga package alone, in the layout of an engine instance export. The same package always writes the same bytes. The engine imports it with cyberia instance <saga-code> --import.

Holds From
The instance and its conf The saga code. The conf names every entity-type default of the backup
Maps Every saga map, with no entities
Entity-type defaults Every saga entity, and every foundation entity a saga map composes
Quests, actions Every saga quest and action, with no source
Object Layer items Every item the defaults, actions and quests name, or a skill summons; no render
Skills, dialogues, the saga The skills of those items, their lines and the action talk, the CyberiaSaga

The command refuses an instance directory that exists: it holds the render and placement of Studio. --force replaces it. An engine export keeps only the quests and actions Studio placed.

An instance with object-layers/ is a complete snapshot: object-layers/<itemId>.json is the definition the item ran when the engine exported it, and an import binds the item to it again. Quests and actions name items by item id. In a snapshot, a quest or an action may also pin an item (objectLayerCid), but only to the definition the snapshot binds it to. validate reports any other pin.

The runtime contract

src/schema/runtime-contract.json holds the runtime vocabulary content uses: item types, entity types, stat bounds, skill handlers, quest step types, the item dialogue prefix and the dialogue moods. The engine owns that vocabulary and generates the file with node bin/cyberia stat-contract. Never edit it.

Global content

src/content/global/<cid>.json holds one Object Layer definition that Cyberia keeps with no world: an import, an item binding no world carries, or stacks players own keep it. The engine writes these files with cyberia content source export-live; never author them by hand. Each file holds:

Field Holds
definition The canonical payload { schemaVersion, profile, data }; its bytes hash to the CID
render null, or the layout and the primary render (base64) the definition names
itemIds The item ids the catalog bound to it at export, sorted
registration Why it stays (import, catalog or owned), who registered it, when and from where

A global definition needs no entity-type default, map, saga or instance. Validation checks the structure; the engine checks the identity and the render when it imports the file.

The artifact

The artifact is data: dist/ and its manifest. It holds no code; the consumer verifies it.

Path Holds
dist/manifest.json Identity and the digest of every file
dist/context.json The context index of the Studio
dist/foundation/<family>.json The compiled foundation, one file per document family
dist/foundation/baseline.json The entity-type defaults a world resolves against
dist/foundation/item-baseline.json The item label a new item of each type takes its function from
dist/procedural/genesis-templates.json Every Genesis Template
dist/procedural/palettes.json The palette families, in order, and every global palette
dist/sagas/<code>/<family>.json Each compiled saga, one file per document family
dist/sagas/<code>/saga.json Its CyberiaSaga record
dist/sagas/<code>/instance.json The shell of its instance
dist/instances/<code>/ Each instance backup
dist/global/<cid>.json Each global content definition

The manifest names repository, contentVersion, sourceRevision, schemaVersion, contentDigest, build, instances, sagas, global and files. The content digest is the sha256 of one <path> <sha256> line per file, in path order. The same commit always builds the same bytes.

The engine reads the artifact of this checkout in development: run build after each commit. pack writes the same artifact as artifacts/cyberia-content-<version>.tgz; the engine reads an extracted copy the same way. A registry, an OCI image or a release asset can carry that tarball later without a change to the artifact.

Release

  1. Change content, run validate, and commit. The build refuses uncommitted content.
  2. Increment version in package.json and commit. A released version never changes.
  3. Run build. The engine reads the new artifact from this checkout.
  4. In the engine, cyberia release lock pins this revision and the artifact in underpost.lock.json of the deployment: repository, revision, version and digest.
  5. A deploy fetches that exact revision, builds it again with npm ci, npm test and npm pack, and fails unless the result matches the lock.

A source channel selects only the repository a deploy fetches the revision from: this repository, or cyberia-content-private. A release from either channel is a production release. A deploy never pushes to either repository.

About

Cyberia MMO World foundation, sagas, procedural generation templates, and versioned content artifacts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages