GithubHelp home page GithubHelp logo

rsek / datasworn Goto Github PK

View Code? Open in Web Editor NEW
123.0 10.0 27.0 50.64 MB

The successor to the original Datasworn repository and Dataforged package, which provide game rules from the Ironsworn and Ironsworn: Starforged TTRPGs in JSON.

Home Page: https://ko-fi.com/r_sek

JavaScript 0.11% C# 16.58% Java 21.83% Python 12.90% Ruby 11.14% Rust 7.59% TypeScript 29.85%
ironsworn ttrpg starforged

datasworn's Introduction

Datasworn v0.0.10

@datasworn/core on npm @datasworn/core on npm Official Ironsworn Discord server Visit the r/Ironsworn subreddit

What is this?

This is a pre-release of the successor to the original Datasworn repository and Dataforged package, which provided game rules from the Ironsworn and Ironsworn: Starforged in JSON.

Until it reaches v1.0, it may receive breaking changes on any version change.

If you're looking for the original Datasworn JSON files, they are available on the legacy branch.

Why a new version?

Some of the design goals for the new standard:

  • provide a format that accomodates both classic Ironsworn and Ironsworn: Starforged
  • language-agnostic JSON schema as the "source of truth", rather than a JSON schema generated from Typescript typings
  • provide type information for languages other than Typescript
  • provide an interchange format that better accomodates homebrew/3rd party content, so it can be imported to any project that relies on the format
  • provide a format friendlier to localization
  • a format and codebase that are less messy, more consistent, and easier to maintain

Usage

Javascript and Typescript

Datasworn spans several NodeJS packages available via npm.

Other languages

Typings for C# (System.Text), Go, Java (Jackson), Python, Ruby, and Rust are available in the json-typedef directory.

These are automatically generated from a JSON TypeDef schema. For the data itself, see below.

JSON

The JSON schema and JSON data are available in the datasworn directory.

Licensing

Core package content (the typings and JSON schema) and internal tooling use the MIT license.

Textual and image content (in other words, the actual content from the rulebooks as described in JSON, Markdown, and other files) is CC-BY-4.0 or CC-BY-NC-4.0.

Additionally, the JSON files embed licensing information in the source property that appears on many objects throughout Datasworn.

Contributors

The previous versions of Datasworn and Dataforged began as unofficial personal projects of rsek, who now maintains Datasworn in an official capacity.

Special thanks to XenotropicDev for allowing me to use data from TheOracle (a Discord bot for use with Ironsworn and Starforged) as the nucleus of the original.

datasworn's People

Contributors

ben avatar cwegrzyn avatar rsek avatar scottbenton avatar vaguegm avatar vks avatar xenotropicdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

datasworn's Issues

Change link and template syntax to accomodate new ID format

Documentating a change already in place on v0.1.0. as : is now used in IDs as a separator,.

Links now just use the ID without additional prefixing: [Some Asset](asset:starforged/path/some_asset)

Double-curly braced template markers now use > as their separator, followed by the full ID: {{table>truth.option.oracle_rollable:starforged/cataclysm.0.sun_plague_cause}}

Embedded IDs are valid for both uses, so long as they meet any type requirements. MarkdownString and TemplateString schema descriptions document these.

Consider a way to provide hints on asset changes to player mechanics that aren't strictly part of a move.

Example from SI (Construct):

You are a machine, and do not eat, drink, or breathe. You Endure Harm as normal, but restore health only when you Repair (spend 1 repair point to take +1 health, and 2 points to clear the wounded impact).

In this specific example, this could mean an override to moves associated with a player condition meter. That's not too hard on its own, but it'd be better if there was a structured, predictable way to override pretty much anything on the player character object -- there's a lot of mechanics that could be described this way.

May interact with #44 #29 #23

Revise ID format to `{type}:{package_id}/{path}`

This should simplify composition and parsing of the IDs, and make it very clear what object type an ID belongs to (as the type ID fragment will always be 1:1 with the object's type value).

examples:

  • starforged/oracle_collection/core (currently starforged/collections/oracles/core)
  • starforged/asset/companions/glowcat (currently starforged/assets/companions/glowcat -- only changes assets to asset)

Aside from rewriting the utilities that interact with IDs, some migration utilities should be provided. The simplest (and most portable) way to do this might be a set of regular expressions. Alternatively, they might be written in Haxe to see how well its cross-compilation holds up.

Create an entity template schema, for describing generation tasks like NPCs and Settlements

FVTT has its own system for this. So does the obsidian plugin, and IIRC Crew Link and Stargazer do, too.

features might include:

  • specify the customary order for rolls
  • specify whether a roll is part of the "first look" at the entity
  • allow picking from one of multiple OracleRollable options for the next roll
  • pull in tags on OracleTableRows (similar to old Dataforged's oracle attributes), and use them to select the next roll (for entities that have a subtype)
  • provide a label for the attribute.
  • fold in the current roll_template property -- either incorporating it, or replacing it entirely
  • should be relatively painless to author a new template
  • templates should be checked against available tags, URLs, etc during post-build validation of JSON
  • allow references to other templates. e.g. "Faction" template pulling in the "Faction Name" template (which is its own entity)

Oracle rolls might be positioned as their own kind of Attribute<T>, alongside Attribute<Int> for stats, condition meters, and so on. Then, player characters and incidental vehicles might be described with the same system, and these properties could be assembled as desired to describe many kinds of 3rd party content.

Example Entity Types

  • Starforged
    • NPC
    • Creature
    • Settlement
    • Starship
    • Derelict
    • Precursor Vault
    • Planet
    • Space Sighting ("near" and "far")
    • Faction

Provide SF (and SI) asset icons

The vector images need some additional processing to make them useful for UX. Much of this will have to be done by manipulating the SVG tags directly.

  • a white ground element inserted below the icon, so that the transparent layers are opaque (otherwise, anything other than a white background looks bad)
  • offering the icons without frames (hexagon in SF, circle in SI)

Rewrite Datasworn type composition/codegen as AST

Currently, Datasworn uses a set of functions to generate TS types from the JSON schema, and JTD for everything else. I'd like to phase out JTD as I think it's not meeting Datasworn's needs, particularly around class inheritance.

To replace it, I'm developing a Datasworn-specific AST that represents shapes common in Datasworn. These might be converted from JSON schema, or serve as a new "source of truth" that composes the JSON schema. Initially it will only generate TS and Java output, but the idea is to make it (relatively) easy to add code generation for any language.

Add `Move` property `allow_momentum_burn`

For progress rolls, this should be a const of false.

For action rolls, this should default to true, but can be manually overridden

Example: asset ability move in "Lucky Figurehead".

Provide examples of AJV JSON schema validation with Datasworn

  • show validation of an entire RulesPackage object
  • show validation primary/embeddable node types individually (and, ideally, for any subschema in definitions)
  • show how to insert defaults when validating
  • provide a config object -- or even a separate package with an AJV dependency, that serves as a friendlier wrapper?
  • what should people who only need one major category of schemas (e.g. oracles) do? it's a big schema!

Express type inheritance and generic type parameters in generated Typescript code

Internally, the JSON schema (which is the source of truth for all typings) is composed in ways that parallel common OOP patterns like class inheritance and generic type parameters.

This information could be attached as a symbol property during TypeBox composition. Ideally, it will be expressed in a language-agnostic way; for the time being it would just be used for TS types, but it may be useful for Python, too (see #62).

Standardize how major nodes are embedded in other nodes, e.g. asset moves, moves oracles

A standalone move/asset/etc should be content-complete without specifying a whole Datasworn tree.

  • tables are commonly embedded in moves
    • these should be distinct from external tables that are relevant to a move, like "Story Clue" in SF
  • Some moves (Ask the Oracle) have multiple embedded tables
  • Asset moves
  • There's at least one example of a table being embedded in an asset (Parrot)
  • Should these nodes have IDs? How should they be constructed?
    • asset moves need to be referenced occasionally. if they don't have IDs, they should have some other means of pointing to them

Allow more than 3 levels of depth for `RecursiveCollection`

This isn't strictly enforced by the schemas right now, but the ID regular expressions currently allow no more than 3 levels deep. 3 is a somewhat arbitrary choice. I figure it's safer (and easier to accomodate in UX design) if there's a maximum.

Some SI oracles manage to exceed this limit, however. Bumping the limit to 4 would accomodate them. I wouldn't feel awful about pushing that to 5 so there's a little extra headroom, however.

TODO

  • centralize DEPTH_MAX as a single constant referenced by schema gen and code gen
  • explore adding some depth limitation to the JSON schema itself (this will require some schema-only intersects that don't really translate to type systems)
  • enforce depth limit in post-build validation

Consider relaxing some `DictKey` and `RulesPackageId` constraints

Currently, DictKey is constrained to [a-z][a-z_]+ and RulesPackageId is constrainted to [a-z][a-z_0-9]{3,}.

Now that IDs are also disambiguated with . separators, it may bear revisisting these restrictions. It'd be nice if they used the same constraint. If they both use [a-z][a-z_0-9]+, any path segment starting with [a-z] can unambiguously be parsed as a string.

This isn't a breaking change to the schema, as the new values would be a superset of the old values. However, there's some existing canonical keys/IDs that ought to be revisited for consistency's sake (e.g. field_one => field_1). So it should probably be included with v0.1.0, which already requires some ID migrations.

Replace `Suggestions` object with an array of ID references (of any kind)

The idea is to allow suggestions for ID formats that may not be included in the current package.

Each of these IDs might simply be a string, or wrapped in an object that allows additional metadata to be included. The object could provide a way to discriminate the ID type, if for some reason the ID can't be parsed.

Move `OracleTableRow.min` and `OracleTableRow.max` to their own object in `OracleTableRow.roll`

min and max can be null to represent unrollable rows that should be rendered for display purposes only. both properties must be of the same type. This is not possible to express in some languages, and awkward at best in JSON schema.

A better way to represent this is to make them their own object, and make that object nullable. min can't have a meaningful value without max, so the schema should reflect that.

The resulting RollRange schema may be reusable elsewhere, too. It might even inherit from a more basic IntegerRange schema used to construct e.g. condition meter-like schema.

Create a set of `core` tags for metadata that has niche applications across multiple rules packages

Some of tags might warrant inclusion as full properties in the main schema. But doing every single one of these (especially for properties that are more about describing flavour), the schema could become bloated. Tags are a reasonable place to keep them for now.

Example tags that could be generalized:

requires_deed:
  # for classic ironsworn assets that effectively require a deed
  description: |-
    This asset represents a notable achievement or situation in your story.
    It is not intended for a starting asset, but can be gained when you
    Advance after fulfilling its requirements.
  value_type: boolean
  applies_to: [asset]
requires_allies:
  description: |-
    This object requires allies to function, and is intended for co-op play, or
    guided play with allies. It is not appropriate for solo play.
  value_type: boolean
supernatural:
  description: |-
    This object is supernatural in nature, and is ideal for settings that
    feature supernatural or mythic powers.
  value_type: boolean
technological:
  description: |- 
    This object is technological in nature, and is ideal for settings that
    feature remarkable technologies.
  value_type: boolean

Provide an "ร  la carte" version of the schema for assets, moves, etc

Tools like @effortlessmountain's asset workbench create assets as standalone objects. User-created moves and assets in VTT environments generally work this way, too. Dealing with the entire hierarchy, ID generation, and so on is outside of their scope... for good reason!

There should be a way to produce portable JSON data for moves and assets. other types would be a nice addition.

Goals

  • schema + typings that are automatically generated from the standard JSON schema, similar to how DataswornSource is generated from the master Datasworn schema (really, DataswornSource could be used close to as-is...)
    • these should be distributed as part of @datasworn/core, and JSON TypeDefs should be provided for other languages
    • should each type be a separate schema document, or should the root schema be a discriminated union?
  • standalone assets/moves should readily integrate into the tree hierarchy if someone wishes to package them for distribution
  • ideally, this schema should be friendly to libraries that generate forms from JSON schema.
    • if/then-based discriminated unions may be rewritten as normal unions.
    • patternProperties seems to be a sticking point of many libraries. is there a specific tool that i can target?
    • would it make sense to write custom tooling for this?

Consider collapsing `summary` and `description` properties into just `description` for certain node types

Collections and oracles have both. Originally, summary was for the short text and description was for longer text.

This is intended to hint the expected text size to developers, but since both properties are optional, in practice people just do something like const foo = node.summary ?? node.description. Longer descriptions from the book also have implications re: licensing.

I think it'd be better to just use description, but at the length currently used by summary.

Add a new `RulesPackage` subtype for `Ruleset`-agnostic content

While Moves and Assets are very sensitive to rules changes, many Datasworn node types are functionally Ruleset-agnostic. It'd be cool to allow RulesPackages that are explicitly Ruleset-agnostic, and can safely be imported in just about any environment.

Node types friendly to this:

  • AtlasEntry + AtlasCollection
  • Npc + NpcCollection
  • OracleRollable + OracleCollection
  • Truth
  • Tag - opens up some interesting possibilities for tag-only packages...

Schema design/composition here is trivial; I think the hardest part here will be coming up with a descriptive name for the subtype

Add `factions` property to Truths

SI truths include a section for related faction ideas. This is formatted as a single paragraph in the original text:

A seafaring tribe seeks to locate and unite scattered people displaced during the Sundering. An order of sorcerers exploits the chaotic forces that caused the cataclysm.

I this would be useful presented as an array of strings: one string per faction/sentence.

Provide tools for Datasworn migration

  • keep a history of generated types/schemata, each in their own folder. simplest way: make it part of e.g. build:schema, with the output path being src/migration/history/{semver}
    • put this in place now to lay groundwork for later
  • programmatically check for relevant schema changes (change name, type, or properties, not description), throw during package build if theres no migration available.
    • should happen for even trivial renames. sometimes thatll mean an empty function, but it needs to be a conscious choice
  • id migrations should include a regex pattern + a replacement template string using the regex capture groups
  • consider ways to make this useful for non-js platforms.
    • id regexes could be presented as a JSON dictionary object (with its own schema). key is the regex string, value is the replacement string. (validation for this: check capture groups by running the replacer function, and seeing if theres any unfilled ones by matching \$\d

Prefix links in markdown text with `datasworn:`

As discussed in discord, prefixing the IDs with a consistent, URI-valid scheme such as datasworn: would resolve issues with parsing the markdown links as URIs and make it easier for implementations, especially if markdown text could contain non-datasworn links (such as a third party package linking to a more complete description on the web)

Provide an `Expansion`-type package for Sundered Isles

This is already underway (on a local branch based on v0.1.0). Most of the data entry and annotations (ID pointers, links, etc) is already complete. Some schema changes must be made to describe e.g. incidental vehicles, but I'm comfortable doing a (pre?) release without them.

The branch will be made public once Sundered Isles' text is finalized and sent to the printer; a prerelease package will be pushed to NPM soon after.

Expose `RulesPackageBuilder` class in `@datasworn/core`

A RulesPackageBuilder instance assembles multiple DataswornSource.RulesPackage objects in to a single Datasworn.RulesPackage file. It does so by merging the objects and assigning IDs. It performs some validations that aren't possible with JSON schema.

Datasworn-specific validations

  • checks table row dice ranges for coherence against the dice property of their parent OracleRollable
  • when provided with an iterable of valid IDs, it checks all ID-type properties for validity, as well as any datasworn ID references made in markdown links or template macros

Notes

  • it does not handle read/write operations; if you want to build from JSON/YAML files, you'll need to load + deserialize them first
  • it must be provided with some external source of JSON schema validation for both the DataswornSource (incoming data) and Datasworn (outgoing data) schemata.

TODO

The coding side of this is mostly done, but there's some nontrivial documentation outstanding.

  • finishing JSdoc annotations for exposed methods/properties
  • provide example(s) of use
  • (optional) add validation of referenced stats in moves/assets

Explore folding all ID patterns in to recursive collectable/collection IDs

This will have a few effects:

  • reduce the number of basic ID patterns -- everything that isn't a rules package will be (what's currently called) RecursiveCollectableId or RecursiveCollectionId
  • opens up recursion in collections that previously didn't have the option, like assets and moves
  • opens up (recursive) collections in types that previously didn't have the option, like setting truths

This does mean that some types will require a "wrapper" folder around them, as Datasworn doesn't allow collectables to live in the "type root" (e.g. starforged.moves) -- only collections can be placed there.

Consider formulating `NpcVariant` as `EmbeddedNpc`

Complicating factor: Datasworn's constants assume that an embedded type dictionary uses the same key as the primary type dictionary in the RulesPackage object. That'd mean that NPC variants live in Npc#npcs rather than Npc#variants, which I don't care for.

It's possible to change that, but would mean adding some additional constants and checks to e.g. IdParser

Standardize collection keys for oracles and assets in SI and SF

Sometimes they're plural, sometimes they're not. "Well-known" keys like companion/companions are likely targets for Wildcards, so they need to be consistent within a given ruleset.

May be a good idea to do this on classic and delve as well, for consistency's sake.

This should be documented (at least in the schema for now). Some assistance for migration would be a good idea as well, most likely in the form of regular expressions.

Fold `OracleTableRow` into embedded type system as `OracleRollableRow`

The material changes to the schema would be as follows:

  • OracleTableRow schema renamed to OracleRollableRow, to follow the naming conventions used by other embed-only types.
  • rows receive an OracleRollableRow embedded ID
    • On a primary OracleRollable: oracle_rollable.row:{oracleRollableID}.{rowIndex}
    • On an EmbeddedOracleRollable in a move: move.oracle_rollable.row:{moveId}.{oracleRollableKey}.{rowIndex}
    • On an EmbeddedOracleRollable in a truth option: truth.option.oracle_rollable.row:{truthId}.{optionIndex}.{oracleRollableKey}.{rowIndex}

Add JS code generation for ID regular expressions

These are already generated for (and made available in) the JSON schema. But offering them as JS RegExp objects offers a few benefits to folks using the language:

  • don't have to load and traverse the Datasworn schema (which is pretty big) to get them
  • provide features like named capture groups; the group names can correspond to the parts of the type prefix

This is mainly a matter of adding another script to Node package codegen; most of the required parts already exist. I think it's a good candidate for v0.1.0.

Use stricter dependency version requirements for 0.x.y releases

Datasworn may receive breaking changes on any version change (consistent with its 0.x.y semver). However, the semver notation in package.json indicates compatibility with anything of the same major (0), so NodeJS dependency resolution behaves in unintended ways.

It'd be better to require an exact version match, which would at least provide a useful error message rather than silently resolving to functionally incompatible versions of various datasworn packages.

Consider ways to describe momentum behaviours that aren't part of a specific move (trigger on burn, adjust reset value, etc)

At minimum, they should provide text describing the trigger condition and the effect.

I'm wary of adding too much mechanical detail here, but adjustments to reset value might also provide the integer value of the adjustment.

Note that game mechanics distinguish between two operations which may be functionally identical: "take +X momentum after reset" and "raise/lower momentum reset value". But, the distinction may be worth retaining, as the qualitative "texture" of the operation is different (or so I remember from when I asked Shawn about it a while back).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.