Development whiteboard: Difference between revisions
m (→Content: set content type) |
|||
(20 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== | == Game architecture == | ||
[[GameObject|Game objects]]. The game engine consists of predefined shapes which can be used to build worlds. | |||
This should simplify many aspects - fixed collision shapes, for example, less assets to synchronize. | |||
Server and Client communicate about GameObjects. | |||
Client threading: | |||
* Main thread | |||
* Rendering by OffscreenCanvas ([https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas MDN], [https://threejs.org/manual/?q=off#en/offscreencanvas three.js]) | |||
* Physics process by [https://rapier.rs/docs/user_guides/javascript/getting_started_js Rapier] | |||
* Networking. Currently websockets (TCP, slow), possibly WebRTC? | |||
== Web services == | |||
=== Auth microservice === | === Auth microservice === | ||
Line 75: | Line 89: | ||
| | | | ||
|now() | |now() | ||
|- | |||
|deleted_at | |||
|datetime | |||
| | |||
| | |||
|} | |} | ||
Line 103: | Line 122: | ||
|enum | |enum | ||
<code>(generic, activation,</code> | <code>(generic, activation,</code> | ||
<code>deactivation, password,</code><code>login, gdpr, totp,</code><code>public_key, recovery, refresh)</code> | |||
<code>deactivation, password,</code> | |||
<code>login, gdpr, totp,</code> | |||
<code>public_key, recovery, refresh)</code> | |||
|Token type | |Token type | ||
| | | | ||
Line 154: | Line 178: | ||
|- | |- | ||
|cidr | |cidr | ||
| | |int 3 | ||
|Banned IP netmask | |Banned IP netmask | ||
|32 | |32 - single address | ||
|- | |- | ||
|user_id | |user_id | ||
Line 203: | Line 227: | ||
|Privilege | |Privilege | ||
| | | | ||
|- | |- | ||
|created_by | |created_by | ||
Line 252: | Line 271: | ||
|Parent role ID | |Parent role ID | ||
| | | | ||
|- | |- | ||
|created_by | |created_by | ||
Line 280: | Line 294: | ||
=== Catalog microservice === | === Catalog microservice === | ||
This microservice contains the store, ownership and "physical" representation of the games. | |||
==== Catalog categories ==== | |||
This is for searching content types more easily. | |||
{| class="wikitable" | |||
|+content category | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
|autoincrement | |||
|- | |||
|category* | |||
|text | |||
|Category | |||
| | |||
|- | |||
|parent_id | |||
|FK int 10 | |||
|Parent category ID | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+content category content type | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
|autoincrement | |||
|- | |||
|content_type* | |||
|enum | |||
|Content.type enum | |||
| | |||
|- | |||
|category_id | |||
|FK int 10 | |||
|Category ID | |||
| | |||
|} | |||
==== Content ==== | ==== Content ==== | ||
Line 307: | Line 369: | ||
|FK UUID | |FK UUID | ||
|Creator ID | |Creator ID | ||
| | |||
|- | |||
|parent_id | |||
|FK int 10 | |||
|Parent content ID | |||
| | | | ||
|- | |- | ||
Line 316: | Line 383: | ||
|onsale* | |onsale* | ||
|boolean | |boolean | ||
|If true, asset is available for sale. If no prices defined, is free | |If true, asset is available for sale. If no prices defined, is free. | ||
Field has no effect on games unless prices are also defined. | |||
|false | |false | ||
|- | |- | ||
Line 323: | Line 391: | ||
|If false, only visible to the creator (and moderators) | |If false, only visible to the creator (and moderators) | ||
|false | |false | ||
|- | |||
|comments_enabled* | |||
|boolean | |||
|Comments enabled | |||
|true | |||
|- | |||
|privacy* | |||
|enum (public, friends, unlisted, private) | |||
|Only applies to games(?) | |||
Visibility of content on the platform. | |||
|public | |||
|- | |- | ||
|type* | |type* | ||
|enum | |enum | ||
|Content type | |Content type. | ||
* Generic: content, set | |||
* Character items: character, hat, accessory, front, back, tool | |||
* Creator items: mesh, texture, gameobject, sound, animation | |||
* Comments: comment, status | |||
* Games: game, world | |||
|content | |content | ||
|- | |- | ||
| | |open_source* | ||
|boolean | |boolean | ||
|Content is open source - can be downloaded / reused | |Content is open source - can be downloaded / reused | ||
|false | |false | ||
|- | |||
|tradeable* | |||
|boolean | |||
|Marks this item as tradeable. | |||
Forbidden on: <code>content</code>, Creator items, Comments, Games | |||
|false | |||
|- | |||
|marketable* | |||
|boolean | |||
|If true, users can resell their owned copies of this content. | |||
Doesn't make much sense without a limited stock. | |||
Forbidden on: <code>content</code>, Creator items, Comments, Games | |||
|false | |||
|- | |||
|stock | |||
|int | |||
|Max sold item count. | |||
Forbidden on: <code>content</code>, Creator items, Comments, Games | |||
| | |||
|- | |- | ||
|license | |license | ||
Line 347: | Line 451: | ||
|FK UUID | |FK UUID | ||
|User id | |User id | ||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|deleted_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Content revision | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Revision ID | |||
| | |||
|- | |||
|content_id* | |||
|FK int 10 | |||
|Content ID | |||
| | |||
|- | |||
|created_by* | |||
|FK UUID | |||
|User ID | |||
| | |||
|- | |||
|updated_by | |||
|FK UUID | |||
| | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|deleted_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Content relation | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Revision ID | |||
| | |||
|- | |||
|first_content_id* | |||
|FK int 10 | |||
|Content ID | |||
| | |||
|- | |||
|second_content_id* | |||
|FK int 10 | |||
|Second content ID. | |||
Second content is <relation> of the first. | |||
| | |||
|- | |||
|relation* | |||
|enum | |||
|Relation type | |||
* support - Second content supports first | |||
* depend - Second content depends on first | |||
* variant - Second content is variant of first | |||
* alternative - Second content is alternative to first | |||
* visual - Second content is a visualization of first | |||
* related - Second content is related to first | |||
* comment - Second content is a comment | |||
* part - Second content is part of first | |||
| | |||
|- | |||
|relation_name | |||
|string | |||
|More detailed name of the relation (thumbnail, icon, texture, character) | |||
| | |||
|- | |||
|created_by* | |||
|FK UUID | |||
|User ID | |||
| | |||
|- | |||
|updated_by | |||
|FK UUID | |||
| | |||
| | | | ||
|- | |- | ||
Line 374: | Line 587: | ||
|FK int 10 | |FK int 10 | ||
|Content ID | |Content ID | ||
| | |||
|- | |||
|revision_id* | |||
|FK int 10 | |||
|Revision ID | |||
| | | | ||
|- | |- | ||
|action* | |action* | ||
|enum (approve, reject, forward) | |enum (pending, approve, reject, forward) | ||
|Moderator action | |Moderator action | ||
| | |pending | ||
|- | |- | ||
|user_id | |user_id | ||
|FK UUID | |FK UUID | ||
|Moderator user ID | |Moderator user ID | ||
Line 396: | Line 614: | ||
|Moderator ordered the deletion of related assets | |Moderator ordered the deletion of related assets | ||
from the system. | from the system. | ||
| | |false | ||
|- | |- | ||
|rejection_reason | |rejection_reason | ||
Line 417: | Line 635: | ||
| | | | ||
| | | | ||
|- | |||
|decided_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
| colspan="4" |M2M relation with bans | |||
|} | |} | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 433: | Line 658: | ||
|FK int 10 | |FK int 10 | ||
|Content ID | |Content ID | ||
| | |||
|- | |||
|revision_id* | |||
|FK int 10 | |||
|Revision ID | |||
| | | | ||
|- | |- | ||
Line 444: | Line 674: | ||
<code>mesh, animation, gameobject,</code> | <code>mesh, animation, gameobject,</code> | ||
<code>world, sound)</code> | <code>world, character, sound)</code> | ||
|Type of asset | |Type of asset | ||
| | | | ||
Line 476: | Line 706: | ||
|- | |- | ||
|price* | |price* | ||
| | |integer | ||
| | |No decimals | ||
| | |0 | ||
|- | |- | ||
|currency* | |currency* | ||
Line 506: | Line 736: | ||
|} | |} | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ | |+Content ownership relation | ||
!Key | !Key | ||
!Type | !Type | ||
Line 513: | Line 743: | ||
|- | |- | ||
|id* | |id* | ||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|content_id* | |||
|FK int 10 | |FK int 10 | ||
|Content ID | |Content ID | ||
| | | | ||
|- | |- | ||
| | |source* | ||
|enum ( | |enum (author, purchase, trade, gift) | ||
|Obtained by action | |||
|author | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID | |||
| | |||
|- | |||
|previous_ownership_id | |||
|FK int 10 | |||
|Previous ownership ID. This is used by the system to track the ownership of items and trace trades. | |||
The previous ownership entity must have its ended_at date set. | |||
| | |||
|- | |||
|purchase_price | |||
|integer | |||
|Purchase price | |||
| | |||
|- | |||
|purchase_currency | |||
|enum (whole, denom) | |||
|Purchase price currency | |||
| | |||
|- | |||
|serial | |||
|int 10 | |||
|Serial number of item | |||
| | |||
|- | |||
|created_by | |||
|FK UUID | |||
|User id | |||
| | |||
|- | |||
|updated_by | |||
|FK UUID | |||
|User id | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|ended_at | |||
|datetime | |||
|Ownership end date and time. | |||
If this is not null, the related user does not own this item anymore. | |||
| | |||
|- | |||
|expires_at | |||
|datetime | |||
|Ownership expiry date and time. | |||
Some items could be purchased for a certain amount of time only. | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Trade | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID | |||
| | | | ||
|- | |- | ||
|recipient_id* | |||
|FK UUID | |||
|User ID | |||
| | | | ||
|- | |||
|status* | |||
|enum | |||
|Status: | |||
# sent | |||
# opened | |||
# rejected | |||
# return_to_sender | |||
# confirmed | |||
# cancelled | |||
|sent | |||
|- | |||
|description | |||
|text | |||
|Trade description | |||
| | | | ||
|- | |||
|created_at | |||
|datetime | |||
| | | | ||
| | | | ||
|- | |- | ||
|updated_at | |||
|datetime | |||
| | | | ||
| | | | ||
|- | |||
| colspan="4" |M2M join tables: user-content-ownership, recipient-content-ownership | |||
|} | |||
{| class="wikitable" | |||
|+Favorite | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|content_id* | |||
|FK int 10 | |||
|Content ID | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | | | ||
| | | | ||
|} | |} | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ | |+Content vote | ||
!Key | !Key | ||
!Type | !Type | ||
Line 540: | Line 906: | ||
|- | |- | ||
|id* | |id* | ||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|content_id* | |||
|FK int 10 | |FK int 10 | ||
|Content ID | |Content ID | ||
| | | | ||
|- | |- | ||
|user_id* | |||
|FK UUID | |||
|User ID | |||
| | |||
|- | |||
|vote* | |||
|enum (up, down) | |||
|Up or down vote | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | | | ||
| | | | ||
|- | |||
|updated_at | |||
|datetime | |||
| | | | ||
| | | | ||
|} | |} | ||
{| class="wikitable" | {| class="wikitable" | ||
|+Content | |+Content report | ||
!Key | !Key | ||
!Type | !Type | ||
Line 566: | Line 952: | ||
| | | | ||
|- | |- | ||
| | |user_id* | ||
|enum ( | |FK UUID | ||
| | |User ID | ||
| | | | ||
|- | |||
|moderator_id | |||
|FK UUID | |||
|Moderator ID | |||
| | |||
|- | |||
|reason* | |||
|text | |||
|Report reason | |||
| | |||
|- | |||
|description* | |||
|text | |||
|Report description | |||
| | |||
|- | |||
|status* | |||
|enum (open, closed, invalid, resolved) | |||
|Moderator's resolution | |||
|open | |||
|- | |||
|revision_id | |||
|FK int | |||
|Reported revision | |||
| | |||
|- | |||
|notes | |||
|text | |||
|Moderator's notes | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|resolved_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
| colspan="4" |M2M relation with moderator action | |||
|} | |||
=== Game microservice === | |||
Game feature flags. | |||
{| class="wikitable" | |||
|+Game | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|FK int 10 | |||
|Game ID, same as the Content ID | |||
| | |||
|- | |||
|hosted* | |||
|boolean | |||
|If true, only uses self-hosted servers | |||
|false | |||
|- | |||
|max_players* | |||
|int | |||
|Max player count | |||
|16 | |||
|} | |||
{| class="wikitable" | |||
|+Game supports | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|game_id* | |||
|FK int 10 | |||
|Game ID | |||
| | |||
|- | |||
|flag* | |||
|enum | |||
|Support flag: | |||
* character | |||
* individual character features | |||
* chat | |||
| | |||
|- | |||
|enabled* | |||
|boolean | |||
|Flag is enabled | |||
|true | |||
|- | |||
|content_id | |||
|FK int 10 | |||
|Supported content ID (character) | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Game play | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|game_id* | |||
|FK int 10 | |||
|Game ID | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User Id | |||
| | |||
|- | |||
|start_time* | |||
|datetime | |||
|Play start time | |||
|now() | |||
|- | |||
|end_time | |||
|datetime | |||
|Play end time | |||
| | |||
|} | |||
=== Server microservice === | |||
Manages servers. | |||
Provisioning hosts can be used to spawn new servers or remove inactive ones depending on the load. The web platform microservice only keeps track of servers, it does not itself shut down or create new servers. Static "always-on" servers can be configured manually by administrators. | |||
The session service will request a server for a game from the server service. Servers which contain friends of the requested user and have free player slots will be preferred. If no servers are available, provision hosts are contacted and a new server is requested. Provisioning hosts usually create multiple servers at once, provided they have the slots, to alleviate bigger player influxes. | |||
{| class="wikitable" | |||
|+Server provisioning host | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|token* | |||
|text | |||
|Server host token | |||
| | |||
|- | |||
|api_url* | |||
|text | |||
|API URL | |||
| | |||
|- | |||
|official* | |||
|boolean | |||
| | |||
|true | |||
|- | |||
|active* | |||
|boolean | |||
| | |||
|true | |||
|- | |||
|pinged_at | |||
|datetime | |||
|Last ping time | |||
| | |||
|- | |||
|capacity* | |||
|int | |||
|Max capacity (number of server slots) | |||
| | |||
|- | |||
|slots* | |||
|int | |||
|Server slots remaining | |||
| | |||
|- | |||
|updated_by | |||
|FK UUID | |||
|Admin user ID | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
Game servers can be created by administrators or by the system via provisioning hosts to service the entire site (official boolean flag) or by users to service their own games. | |||
If the "provisioned" boolean flag is set, then the server service will decide which game will be loaded in a given server. For user-hosted servers, the games loaded will only be the ones configured by the user. | |||
{| class="wikitable" | |||
|+Hosted game server | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|token* | |||
|text | |||
|Server token | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|Owner user ID | |||
| | |||
|- | |||
|game_id | |||
|FK int 10 | |||
|Currently hosted game ID | |||
| | |||
|- | |||
|socket_host* | |||
|text | |||
|Socket host | |||
| | |||
|- | |||
|socket_port* | |||
|int | |||
|Socket port | |||
| | |||
|- | |||
|api_url* | |||
|text | |||
|HTTP(S) API base URL | |||
| | |||
|- | |||
|country | |||
|varchar 255 | |||
|Country of server | |||
| | |||
|- | |||
|provisioned* | |||
|boolean | |||
|If true, current game can be chosen by server service | |||
|false | |||
|- | |||
|quarantine* | |||
|boolean | |||
|If true, cannot be joined to. Set by moderators. | |||
|false | |||
|- | |||
|official* | |||
|boolean | |||
|Official provisioned server | |||
|false | |||
|- | |||
|active* | |||
|boolean | |||
|If false, server is not used for new sessions | |||
|true | |||
|- | |||
|server_info | |||
|json | |||
|Server-uploaded information about itself | |||
| | |||
|- | |||
|player_count | |||
|int | |||
|Player count from last ping | |||
| | |||
|- | |||
|ping | |||
|int | |||
|Last ping in milliseconds | |||
| | |||
|- | |||
|provisioned_by | |||
|FK int | |||
|Provisioning host ID, if applicable | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|pinged_at | |||
|datetime | |||
|Server keepalive ping | |||
| | |||
|- | |||
| colspan="4" |M2M relation with games for multi-game support | |||
|} | |||
Host bans differ from user (IP) bans. It is possible to ban a server or network for being used to provide hosting without banning users. | |||
{| class="wikitable" | |||
|+Host ban | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|ip* | |||
|varchar 255 | |||
|Server IP | |||
| | |||
|- | |||
|cidr* | |||
|int 3 | |||
|Server IP netmask | |||
|32 | |||
|- | |||
|admin_id* | |||
|FK UUID | |||
|Admin user ID | |||
| | |||
|- | |||
|user_id | |||
|FK UUID | |||
|Banned user ID | |||
| | |||
|- | |||
|reason* | |||
|text | |||
|Reason for network ban | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|expires_at | |||
|datetime | |||
|If null, does not expire | |||
| | |||
|} | |||
=== Session microservice === | |||
Manages sessions. | |||
==== Session ==== | |||
Created when player presses Play. Server gets token on connection. Server validates token against service and receives character. | |||
{| class="wikitable" | |||
|+ | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
|Relation ID | |||
| | |||
|- | |||
|token* | |||
|text | |||
|Session token | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|Owner user ID | |||
| | |||
|- | |||
|character_id* | |||
|FK int 10 | |||
|Character ID | |||
| | |||
|- | |||
|game_id* | |||
|FK int 10 | |||
|Played game ID | |||
| | |||
|- | |||
|server_id* | |||
|FK int 10 | |||
|Server ID | |||
| | |||
|- | |||
|server_type* | |||
|enum (host, provision) | |||
|Server type | |||
|provision | |||
|- | |||
|created_at* | |||
|datetime | |||
| | |||
| | |||
|- | |||
|joined_at | |||
|datetime | |||
|Set when the server validates the token | |||
| | |||
|- | |||
|pinged_at | |||
|datetime | |||
|Session keepalive ping | |||
| | |||
|} | |||
=== Player microservice === | |||
==== Character ==== | |||
{| class="wikitable" | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |- | ||
|user_id* | |user_id* | ||
Line 576: | Line 1,404: | ||
| | | | ||
|- | |- | ||
| | |content_id* | ||
|FK int 10 | |||
|Character content type ID | |||
| | |||
|- | |||
|name | |||
|text | |||
|Character name | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Character properties | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|character_id | |||
|FK int 10 | |||
|Character ID | |||
| | |||
|- | |||
|property* | |||
|varchar 255 | |||
|Character Property | |||
| | |||
|- | |||
|value* | |||
|text | |||
|Property Value | |||
| | |||
|- | |||
|value_type* | |||
|enum | |||
|Property Value type | |||
| | |||
|- | |||
|related_content_id | |||
|FK int 10 | |||
|Content ID | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Character worn item | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|character_id | |||
|FK int 10 | |||
|Character ID | |||
| | |||
|- | |||
|content_id | |||
|FK int 10 | |FK int 10 | ||
| | |Content ID | ||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
==== Friends ==== | |||
{| class="wikitable" | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID (Requester) | |||
| | |||
|- | |||
|target_id* | |||
|FK UUID | |||
|Second user ID | |||
| | |||
|- | |||
|pending* | |||
|boolean | |||
|Is pending request | |||
|true | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
==== Follow ==== | |||
{| class="wikitable" | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID (Follower) | |||
| | |||
|- | |||
|target_id* | |||
|FK UUID | |||
|Second user ID (Followee) | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
==== Block ==== | |||
{| class="wikitable" | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID (Blocker) | |||
| | |||
|- | |||
|target_id* | |||
|FK UUID | |||
|Second user ID (Blockee) | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | | | ||
|} | |||
=== Bank microservice === | |||
==== Currencies ==== | |||
{| class="wikitable" | |||
|+Definition | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |- | ||
| | |id* | ||
| | |PK int 10 | ||
| | | | ||
| | | | ||
|- | |- | ||
| | |type* | ||
|enum (whole, denom) | |enum (whole, denom) | ||
| | |Currency type | ||
| | |||
|- | |||
|name* | |||
|varchar 255 | |||
|Currency name | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Conversion | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|currency_source_id* | |||
|FK int 10 | |||
| | |||
| | |||
|- | |||
|currency_destination_id* | |||
|FK int 10 | |||
| | |||
| | |||
|- | |||
|ratio* | |||
|int | |||
|Conversion ratio | |||
| | |||
|- | |||
|volume | |||
|int | |||
| | |||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|valid_from* | |||
|datetime | |||
| | |||
| | |||
|- | |||
|valid_to | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Account balance | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|currency_id* | |||
|FK int 10 | |||
| | |||
| | |||
|- | |||
|user_id* | |||
|FK UUID | |||
|User ID | |||
| | | | ||
|- | |- | ||
| | |amount | ||
|int 10 | |int 10 | ||
| | |Amount | ||
| | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |||
| | |||
| | |||
|} | |||
{| class="wikitable" | |||
|+Transaction | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK int 10 | |||
| | |||
| | |||
|- | |||
|currency_id* | |||
|FK int 10 | |||
| | |||
| | | | ||
|- | |- | ||
| | |user_id* | ||
|FK UUID | |FK UUID | ||
|User | |User ID | ||
| | | | ||
|- | |- | ||
| | |recipient_id* | ||
|FK UUID | |FK UUID | ||
|User | |User ID | ||
| | |||
|- | |||
|previous_transaction_id | |||
|FK int 10 | |||
|Previous transaction ID, usually for rollbacks/refunds | |||
| | |||
|- | |||
|description | |||
|text | |||
|Transaction description | |||
| | |||
|- | |||
|amount | |||
|int 10 | |||
|Amount | |||
| | |||
|- | |||
|confirmed* | |||
|boolean | |||
| | | | ||
|false | |||
|- | |||
|automated* | |||
|boolean | |||
|Automatic transaction initiated by platform | |||
|false | |||
|- | |- | ||
|created_at | |created_at | ||
Line 615: | Line 1,792: | ||
|datetime | |datetime | ||
| | | | ||
| | |||
|} | |||
=== Assets microservice === | |||
Manages assets, forwards them from S3-compatible buckets. | |||
{| class="wikitable" | |||
!Key | |||
!Type | |||
!Description | |||
!Default | |||
|- | |||
|id* | |||
|PK UUID | |||
| | |||
| | |||
|- | |||
|user_id | |||
|FK UUID | |||
|Created by user | |||
| | |||
|- | |||
|asset_tag | |||
|text | |||
|Asset tag | |||
| | |||
|- | |||
|source_uri | |||
|text | |||
|Data source URI | |||
| | |||
|- | |||
|source | |||
|text | |||
|Data source | |||
| | | | ||
|- | |- | ||
| | |originalname | ||
|text | |||
|Original name | |||
| | |||
|- | |||
|mimetype | |||
|varchar 255 | |||
|Mimetype | |||
| | |||
|- | |||
|filesize | |||
|int | |||
|File size in bytes | |||
| | |||
|- | |||
|upload_ip | |||
|text | |||
|Uploader IP address | |||
| | |||
|- | |||
|public | |||
|boolean | |||
|If false, requires valid token issued by platform to access | |||
|false | |||
|- | |||
|created_at | |||
|datetime | |||
| | |||
| | |||
|- | |||
|updated_at | |||
|datetime | |datetime | ||
| | | | ||
| | | | ||
|- | |- | ||
| | |deleted_at | ||
|datetime | |datetime | ||
| | | | ||
| | | | ||
|} | |} | ||
=== Render microservice === | |||
Render microservice does not have any databases. Its only job is to render 3D assets to 2D thumbnails. | |||
Character accessories are rendered onto supported character models and then uploaded as thumbnail image assets. | |||
GameObjects are also rendered here. | |||
This microservice also does transcoding and reformatting - formatting variable formats into commonly used ones. |
Latest revision as of 17:12, 19 August 2023
Game architecture
Game objects. The game engine consists of predefined shapes which can be used to build worlds.
This should simplify many aspects - fixed collision shapes, for example, less assets to synchronize.
Server and Client communicate about GameObjects.
Client threading:
- Main thread
- Rendering by OffscreenCanvas (MDN, three.js)
- Physics process by Rapier
- Networking. Currently websockets (TCP, slow), possibly WebRTC?
Web services
Auth microservice
Users
Key | Type | Description | Default |
---|---|---|---|
id* | PK UUID | User ID, UUID | uuid_generate_v4()
|
username* | varchar 255 | Username | |
email* | varchar 255 | Email address | |
phone | varchar 255 | Phone number | |
country | varchar 2 | 2-character country code | |
language* | varchar 2 | 2-character language code | en |
password* | text | bcrypt 12 rounds password | |
display_name | text | user-chosen display name | same as username |
verified* | boolean | Email verified | false |
activated* | boolean | Account active | true |
login_at* | datetime | Last login date and time | |
created_at* | datetime | now() | |
updated_at* | datetime | now() | |
deleted_at | datetime |
User tokens
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
token* | text | Token | |
nonce | text | Number-used-once, for challenges | |
type* | enum
|
Token type | |
user_id* | FK UUID | Token owner | |
previous_id | FK int 10 | Previous token ID of the same series.
This is used to prevent refresh token reuse. |
|
expires_at | datetime | Token expiry time | |
created_at* | datetime | now() |
Bans
M2M join tables: ban-privilege.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
reason* | text | Reason for ban | |
ip | varchar 255 | Banned IP | |
cidr | int 3 | Banned IP netmask | 32 - single address |
user_id | FK UUID | Banned user ID.
Not required if IP ban |
|
admin_id* | FK UUID | User who created the ban ID | |
privilege_ban | boolean | This ban only affects certain privileges.
Unless web is included, a notice will not be shown. |
false |
expires_at | datetime | Ban expiry date | |
created_at* | datetime | now() |
Privilege
M2M join tables: role-privilege, user-privilege.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
privilege* | text | Privilege | |
created_by | FK UUID | User id | |
updated_by | FK UUID | User id | |
created_at | datetime | ||
updated_at | datetime |
Role
Tree structure. M2M join tables: role-privilege, user-role.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
role* | text | Privilege | |
parent_id | FK int 10 | Parent role ID | |
created_by | FK UUID | User id | |
updated_by | FK UUID | User id | |
created_at | datetime | ||
updated_at | datetime |
Catalog microservice
This microservice contains the store, ownership and "physical" representation of the games.
Catalog categories
This is for searching content types more easily.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
category* | text | Category | |
parent_id | FK int 10 | Parent category ID |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | autoincrement | |
content_type* | enum | Content.type enum | |
category_id | FK int 10 | Category ID |
Content
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Content ID | |
name* | varchar 255 | Item name | |
description* | text | Item description | |
user_id | FK UUID | Creator ID | |
parent_id | FK int 10 | Parent content ID | |
restricted* | boolean | If true, asset has been restricted by a moderator. | false |
onsale* | boolean | If true, asset is available for sale. If no prices defined, is free.
Field has no effect on games unless prices are also defined. |
false |
published* | boolean | If false, only visible to the creator (and moderators) | false |
comments_enabled* | boolean | Comments enabled | true |
privacy* | enum (public, friends, unlisted, private) | Only applies to games(?)
Visibility of content on the platform. |
public |
type* | enum | Content type.
|
content |
open_source* | boolean | Content is open source - can be downloaded / reused | false |
tradeable* | boolean | Marks this item as tradeable.
Forbidden on: |
false |
marketable* | boolean | If true, users can resell their owned copies of this content.
Doesn't make much sense without a limited stock.
Forbidden on: |
false |
stock | int | Max sold item count.
Forbidden on: |
|
license | text | Optional license text | |
created_by | FK UUID | User id | |
updated_by | FK UUID | User id | |
created_at | datetime | ||
updated_at | datetime | ||
deleted_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Revision ID | |
content_id* | FK int 10 | Content ID | |
created_by* | FK UUID | User ID | |
updated_by | FK UUID | ||
created_at | datetime | ||
updated_at | datetime | ||
deleted_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Revision ID | |
first_content_id* | FK int 10 | Content ID | |
second_content_id* | FK int 10 | Second content ID.
Second content is <relation> of the first. |
|
relation* | enum | Relation type
|
|
relation_name | string | More detailed name of the relation (thumbnail, icon, texture, character) | |
created_by* | FK UUID | User ID | |
updated_by | FK UUID | ||
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Moderation ID | |
content_id* | FK int 10 | Content ID | |
revision_id* | FK int 10 | Revision ID | |
action* | enum (pending, approve, reject, forward) | Moderator action | pending |
user_id | FK UUID | Moderator user ID | |
penalty* | boolean | Moderator penalized the content author.
For example, banned for illegal content. |
false |
asset_delete* | boolean | Moderator ordered the deletion of related assets
from the system. |
false |
rejection_reason | enum (tos, illegal, dmca, other) | Rejection reason | |
description | text | Additional information regarding moderator action | |
created_at | datetime | ||
updated_at | datetime | ||
decided_at | datetime | ||
M2M relation with bans |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
revision_id* | FK int 10 | Revision ID | |
asset_id* | UUID | ID of asset | |
type* | enum (image, texture, texture3d,
|
Type of asset | |
type_name | varchar 255 | Sub-type (preview, icon, etc) | |
index* | int 10 | Asset index | 0 |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
price* | integer | No decimals | 0 |
currency* | enum (whole, denom) | Two-currency system choice | |
created_by | FK UUID | User id | |
updated_by | FK UUID | User id | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
source* | enum (author, purchase, trade, gift) | Obtained by action | author |
user_id* | FK UUID | User ID | |
previous_ownership_id | FK int 10 | Previous ownership ID. This is used by the system to track the ownership of items and trace trades.
The previous ownership entity must have its ended_at date set. |
|
purchase_price | integer | Purchase price | |
purchase_currency | enum (whole, denom) | Purchase price currency | |
serial | int 10 | Serial number of item | |
created_by | FK UUID | User id | |
updated_by | FK UUID | User id | |
created_at | datetime | ||
updated_at | datetime | ||
ended_at | datetime | Ownership end date and time.
If this is not null, the related user does not own this item anymore. |
|
expires_at | datetime | Ownership expiry date and time.
Some items could be purchased for a certain amount of time only. |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
user_id* | FK UUID | User ID | |
recipient_id* | FK UUID | User ID | |
status* | enum | Status:
|
sent |
description | text | Trade description | |
created_at | datetime | ||
updated_at | datetime | ||
M2M join tables: user-content-ownership, recipient-content-ownership |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
user_id* | FK UUID | User ID | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
user_id* | FK UUID | User ID | |
vote* | enum (up, down) | Up or down vote | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
content_id* | FK int 10 | Content ID | |
user_id* | FK UUID | User ID | |
moderator_id | FK UUID | Moderator ID | |
reason* | text | Report reason | |
description* | text | Report description | |
status* | enum (open, closed, invalid, resolved) | Moderator's resolution | open |
revision_id | FK int | Reported revision | |
notes | text | Moderator's notes | |
created_at | datetime | ||
updated_at | datetime | ||
resolved_at | datetime | ||
M2M relation with moderator action |
Game microservice
Game feature flags.
Key | Type | Description | Default |
---|---|---|---|
id* | FK int 10 | Game ID, same as the Content ID | |
hosted* | boolean | If true, only uses self-hosted servers | false |
max_players* | int | Max player count | 16 |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
game_id* | FK int 10 | Game ID | |
flag* | enum | Support flag:
|
|
enabled* | boolean | Flag is enabled | true |
content_id | FK int 10 | Supported content ID (character) |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
game_id* | FK int 10 | Game ID | |
user_id* | FK UUID | User Id | |
start_time* | datetime | Play start time | now() |
end_time | datetime | Play end time |
Server microservice
Manages servers.
Provisioning hosts can be used to spawn new servers or remove inactive ones depending on the load. The web platform microservice only keeps track of servers, it does not itself shut down or create new servers. Static "always-on" servers can be configured manually by administrators.
The session service will request a server for a game from the server service. Servers which contain friends of the requested user and have free player slots will be preferred. If no servers are available, provision hosts are contacted and a new server is requested. Provisioning hosts usually create multiple servers at once, provided they have the slots, to alleviate bigger player influxes.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
token* | text | Server host token | |
api_url* | text | API URL | |
official* | boolean | true | |
active* | boolean | true | |
pinged_at | datetime | Last ping time | |
capacity* | int | Max capacity (number of server slots) | |
slots* | int | Server slots remaining | |
updated_by | FK UUID | Admin user ID | |
updated_at | datetime |
Game servers can be created by administrators or by the system via provisioning hosts to service the entire site (official boolean flag) or by users to service their own games.
If the "provisioned" boolean flag is set, then the server service will decide which game will be loaded in a given server. For user-hosted servers, the games loaded will only be the ones configured by the user.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
token* | text | Server token | |
user_id* | FK UUID | Owner user ID | |
game_id | FK int 10 | Currently hosted game ID | |
socket_host* | text | Socket host | |
socket_port* | int | Socket port | |
api_url* | text | HTTP(S) API base URL | |
country | varchar 255 | Country of server | |
provisioned* | boolean | If true, current game can be chosen by server service | false |
quarantine* | boolean | If true, cannot be joined to. Set by moderators. | false |
official* | boolean | Official provisioned server | false |
active* | boolean | If false, server is not used for new sessions | true |
server_info | json | Server-uploaded information about itself | |
player_count | int | Player count from last ping | |
ping | int | Last ping in milliseconds | |
provisioned_by | FK int | Provisioning host ID, if applicable | |
created_at | datetime | ||
updated_at | datetime | ||
pinged_at | datetime | Server keepalive ping | |
M2M relation with games for multi-game support |
Host bans differ from user (IP) bans. It is possible to ban a server or network for being used to provide hosting without banning users.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
ip* | varchar 255 | Server IP | |
cidr* | int 3 | Server IP netmask | 32 |
admin_id* | FK UUID | Admin user ID | |
user_id | FK UUID | Banned user ID | |
reason* | text | Reason for network ban | |
created_at | datetime | ||
updated_at | datetime | ||
expires_at | datetime | If null, does not expire |
Session microservice
Manages sessions.
Session
Created when player presses Play. Server gets token on connection. Server validates token against service and receives character.
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | Relation ID | |
token* | text | Session token | |
user_id* | FK UUID | Owner user ID | |
character_id* | FK int 10 | Character ID | |
game_id* | FK int 10 | Played game ID | |
server_id* | FK int 10 | Server ID | |
server_type* | enum (host, provision) | Server type | provision |
created_at* | datetime | ||
joined_at | datetime | Set when the server validates the token | |
pinged_at | datetime | Session keepalive ping |
Player microservice
Character
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
user_id* | FK UUID | User ID | |
content_id* | FK int 10 | Character content type ID | |
name | text | Character name | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
character_id | FK int 10 | Character ID | |
property* | varchar 255 | Character Property | |
value* | text | Property Value | |
value_type* | enum | Property Value type | |
related_content_id | FK int 10 | Content ID | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
character_id | FK int 10 | Character ID | |
content_id | FK int 10 | Content ID | |
created_at | datetime | ||
updated_at | datetime |
Friends
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
user_id* | FK UUID | User ID (Requester) | |
target_id* | FK UUID | Second user ID | |
pending* | boolean | Is pending request | true |
created_at | datetime | ||
updated_at | datetime |
Follow
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
user_id* | FK UUID | User ID (Follower) | |
target_id* | FK UUID | Second user ID (Followee) | |
created_at | datetime | ||
updated_at | datetime |
Block
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
user_id* | FK UUID | User ID (Blocker) | |
target_id* | FK UUID | Second user ID (Blockee) | |
created_at | datetime | ||
updated_at | datetime |
Bank microservice
Currencies
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
type* | enum (whole, denom) | Currency type | |
name* | varchar 255 | Currency name | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
currency_source_id* | FK int 10 | ||
currency_destination_id* | FK int 10 | ||
ratio* | int | Conversion ratio | |
volume | int | ||
created_at | datetime | ||
updated_at | datetime | ||
valid_from* | datetime | ||
valid_to | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
currency_id* | FK int 10 | ||
user_id* | FK UUID | User ID | |
amount | int 10 | Amount | |
created_at | datetime | ||
updated_at | datetime |
Key | Type | Description | Default |
---|---|---|---|
id* | PK int 10 | ||
currency_id* | FK int 10 | ||
user_id* | FK UUID | User ID | |
recipient_id* | FK UUID | User ID | |
previous_transaction_id | FK int 10 | Previous transaction ID, usually for rollbacks/refunds | |
description | text | Transaction description | |
amount | int 10 | Amount | |
confirmed* | boolean | false | |
automated* | boolean | Automatic transaction initiated by platform | false |
created_at | datetime | ||
updated_at | datetime |
Assets microservice
Manages assets, forwards them from S3-compatible buckets.
Key | Type | Description | Default |
---|---|---|---|
id* | PK UUID | ||
user_id | FK UUID | Created by user | |
asset_tag | text | Asset tag | |
source_uri | text | Data source URI | |
source | text | Data source | |
originalname | text | Original name | |
mimetype | varchar 255 | Mimetype | |
filesize | int | File size in bytes | |
upload_ip | text | Uploader IP address | |
public | boolean | If false, requires valid token issued by platform to access | false |
created_at | datetime | ||
updated_at | datetime | ||
deleted_at | datetime |
Render microservice
Render microservice does not have any databases. Its only job is to render 3D assets to 2D thumbnails.
Character accessories are rendered onto supported character models and then uploaded as thumbnail image assets.
GameObjects are also rendered here.
This microservice also does transcoding and reformatting - formatting variable formats into commonly used ones.