Skip to content

OnlyWorlds Unity SDK 0.30.0

Choose a tag to compare

@tmoosting tmoosting released this 01 Nov 09:20
· 78 commits to main since this release

Doubles now go through the SDK's JSON exactly on every runtime, Unity's Mono included, where before some were written
or read one step off. The record profile's reader (OWRecord) lists a Character's runs from any game; the account's
own tokens can be listed and revoked; a value that is not one path segment is refused before anything is sent; and
the link forwarder answers a game's own scheme. A minor release because it adds public API (below).

Added

  • The record profile's reader (schema-dist v0.33.0-dist.102, profiles/record.md): a game's run kept in the world
    its Characters live in, an Event marked x_record. OWRecord.MarkOf(element) reads the mark (null for a broken
    one: a played_at that is no real calendar instant, a number seed, a capitalised outcome, a mark on anything but an
    Event); OWRecord.Of(characterId, elements) lists a Character's records newest first, to the millisecond, each with
    their seat and their stories as protagonist, narrator or both. A run or story still proposed is not read. The
    profile's fixture (32 cases) is its test, with the TypeScript SDK 4.124.0's own vectors beside it. It reads the world
    in one pass, the Character's stories found once by each Event they name, as the TypeScript SDK 4.124.1 does (answers
    unchanged); its ties hold 4.124.2's vector (an id above the BMP after U+FF00).
  • Schema pin to v0.33.0-dist.102: the record profile, new; the strand page's ruled line dated. No schema field moved;
    the generated models' headers move with the serial.
  • The link forwarder (Tools~/ow-link) answers a game's own scheme: install.ps1 -Scheme mygame registers
    mygame: links for the user, and the config's scheme names the same. Such a link reaches the listener and the
    player as the ow: address it carries, so nothing on the receiving side changes. ow: stays the default: it is
    the standard's own scheme, and a link in it means whichever OnlyWorlds app a machine has. The installer refuses a
    config that names another scheme than it registers.
  • The Open with menu's own site row says "You are here" when the surface's Tool is onlyworlds (the site itself),
    where before it said "Needs a connection" offline or nothing. Parity with the TypeScript SDK 4.123.0, the shared
    openers fixture re-vendored at 57 cases.
  • Schema pin to v0.33.0-dist.101: the strand profile's Where it shows says what a reader draws. An empty slot as
    the next thing to make is a writer's rule; a surface that only reads may draw the filled slots alone, and still
    shows a half-built strand as the strand. No fixture, schema or reader rule moved; the generated models' headers
    move with the serial.
  • The account's own tokens, in parity with the TypeScript SDK 4.122.0 (its test vector ported).
    ListAccountTokensAsync() lists them (GET /account/tokens) as OWAccountToken rows: by name and last four,
    never the token itself, with when each was last used, whether it is revoked, when it expires, how many live world
    keys it minted, and who it is for (audience, and Client and ReturnHost on an mcp token).
    RevokeAccountTokenAsync(tokenId) revokes one (DELETE /account/tokens/{token_id}), this client's own included. A
    tool done with a sign-in revokes the token by the id the sign-in answered (OWSignedIn.Id from a password
    sign-in, OWSignInResult.TokenId from Sign in with OnlyWorlds). Both need an account token, and
    any other key is refused before sending. They send the Bearer alone. An empty id is refused before sending, and an
    id that is not one of the account's tokens is keel's 404 (IsNotFound).

Changed

  • Parity with the TypeScript SDK 4.123.2: the Open with menu refuses a tools row whose link opens no app.
    OWOpeners.For throws an ArgumentException naming the row and the key when its open.world or open.element
    does not begin with its scheme (a leading space, or a //host link), or its scheme is javascript:, data:,
    vbscript:, file:, blob: or about: in any case, where before it drew the row with that link as its href. Both
    templates of every row are checked on either menu, a row built in code as well as one read by OWTool.FromJson; a
    null template is still no door. The shared openers fixture is re-vendored at 61 cases.
  • Parity with the TypeScript SDK 4.123.3: a value in a request path that is not one segment is refused before
    anything is sent. The API decodes an escaped slash before it routes, so the escape below could not keep an id
    carrying / on its route. Every element type, id, link field, file and proposal id, Character id and account-route
    id (world, key, link, seat, member, token) is now checked: a type must be a lower-case word (^[a-z][a-z0-9_]*$),
    any other value letters, digits, _, . and -, not starting with a dot or a dash. Anything else, an empty
    string or null included, throws an ArgumentException named for the value
    (id "abc/hidden" is not one path segment. Nothing was sent., its ParamName id). What passes is still escaped;
    a uuid, a word id and a real type go out as before.
  • The shared openers fixture is re-vendored at 65 cases, in parity with the TypeScript SDK: one refused case for each
    scheme that opens no app (vbscript:, file:, blob:, about: beside javascript: and data:), so a reader that
    forgot one of the six no longer passes. No reader changed; the six were already refused.
  • OWTools.All carries Little Lens, in parity with the TypeScript SDK 4.123.5. The tools list is repinned at a1573ac
    (from 86208c8): Little Lens, a world as a web of its elements and links, read only, is a listed row, so
    OWOpeners.For offers it in the Open with menu for a world and for an element, to anyone (it needs no account).
    No type or function changed.

Fixed

  • Every value a call puts in a request path is sent as one escaped segment, in parity with the TypeScript SDK
    4.122.1. GetAsync, UpsertAsync, PatchAsync, DeleteAsync, EditLinksAsync, AdoptAsync, HideAsync and
    UnhideAsync put the element id into the path as given, and those and ListAsync, CreateAsync and the files,
    proposal and review routes did the same with the element type, so an id or type carrying a /, ? or # asked a
    different route (GetAsync("character", "abc/hidden") asked GET /character/abc/hidden/). Each is now escaped with
    Uri.EscapeDataString, as the id already was on the files, proposal and review routes and the link field on
    EditLinksAsync. On a real id (the API declares every element id a UUID) and a real type nothing on the wire
    changes. A test reads every request path in the client's source and fails on one that puts a value in unescaped
    or is built in a way it cannot read.
    A null type or id is now refused before anything is sent (see Changed: 4.123.3); before, it went out as an empty
    segment (/character//).
  • Doubles go through the SDK's JSON exactly, both ways, on every runtime. Newtonsoft writes a double with the
    runtime's "R" format and reads one with the runtime's double.TryParse, and under Unity's Mono both are inexact:
    over 19,990 doubles, 15 written strings read back as another double in the API and the TypeScript SDK (one went
    out as 51.6721044378159, which they read as its neighbour), and 63 of the shortest strings those send were read
    one step off (263.2953629956518). The SDK's own write-then-read agreed with itself, so no round trip on Mono
    could see it. What it reached: floats in extension fields (x_*) and any double a caller sends or reads. Now
    OWJson.Serialize, every request body, the world cache's text and an extension's raw JSON write a finite double
    as JSON.stringify writes it (the shortest digits that read back, the closest of those, ECMAScript's layout: the
    writer the world folder already used, now shared and faster), and OWJson.ParseObject and OWJson.Deserialize,
    so every response the client reads as data, read a number with a fraction or an exponent to the nearest double,
    ties to even. Bytes change where JSON.stringify's differ from Newtonsoft's: 0.3333333333333333 (was
    0.33333333333333331), 1e-7 and 1e+21 (were 1E-07 and 1E+21). One exception keeps a reader's types: on
    the wire and through the models an integral double keeps its decimal point (1.0, -0.0), as before, so a float
    in a world stays a float to a reader that types numbers; the world folder writes 1, as its spec rules. Integers, large integers, strings, NaN and the infinities
    are written and read as before. A world folder read under Mono no longer misreads a float the folder writer wrote.