openvibers/openvibe.games Commits
Editor ids carry a per-session tag (two editors in one millisecond no longer collide); the first load is measured (3.72 MB); STATUS.json names today's pins and the creator platform (#166)
Changes
@@@ -6,7 +6,7 @@"runtime": "node 22, TypeScript (tsx), pnpm workspace; Babylon.js (client) + deterministic Rapier physics; PostgreSQL 18 via openvibe-sdk/db (pg, or embedded PGlite in development); Valkey optional","port": 8000,"domain": "openvibe.games, play.openvibe.games",-- "contracts": "openvibe-contracts v0.209.0, openvibe-sdk v0.62.0, openvibe-shared v4.9.0, openvibe-publishing v1.4.0 (apps/server/package.json)",++ "contracts": "openvibe-contracts v0.214.0, openvibe-sdk v0.65.0, openvibe-shared v4.15.2, openvibe-publishing v1.4.0 (apps/server/package.json)","capabilities": ["games.mod.manage","games.mod.read",@@@ -29,6 +29,8 @@"Scraplandia and Salvage Rush in one Games process (M5), in separate place and instance registries; server-scored rounds, per-game achievements and all-time/week leaderboards","scores, unlocks and guest adoptions posted to OpenVibe.Play (GAMES_PLAY_URL)","creator worlds: a published world gets its own page (/worlds/<id>) and is in OpenVibe.Search (openvibe-publishing search-feed)",++ "creators make games the way we do: characters belong to each game, remix a world (credited), its own games-quickjs@1 scripts (run when GAMES_CREATOR_SCRIPTS=1), a team of up to 8 editors by invite link, and a top-down (2D) view",++ "the asset store: builds (pieces placed in the editor) and scripts shared free for anyone's worlds, placed from the editor's Store tab or added from /worlds","Steam's featured lists (top sellers, new releases, specials) read from OpenVibe.Sources (GAMES_SOURCES_URL)","the casual line (plan T22): packages/casual kit, server economy with ledger and idempotent actions, Vibe Heroes at /play/vibe-heroes (guest play, adoption on sign-in, earned-only summons, gem store; paid products wait for Billing)","six achievement rewards granted as free OpenVibe.Inventory items, never sold or traded; GAMES_ITEMS=on/off and GAMES_INVENTORY_URL configure delivery",@@@ -41,5 +43,5 @@"the OpenVibe Frame from its own pinned copy","per-actor limits on capability-boundary writes (openvibe-sdk/limits)"],-- "updated": "2026-10-23"++ "updated": "2026-10-27"}@@@ -9,10 +9,15 @@ import type { StaticBody } from '@openvibe/content'export type Tool = 'terrain' | 'paint' | 'entity' | 'mesh' | 'select' | 'face' | 'light' | 'zone'--/** Session-stable id generator for map objects (never array positions). */++/**++ * Session-stable id generator for map objects (never array positions). The time and counter alone repeat across++ * sessions: two editors on one map (collaboration, or a team) placing in the same millisecond with the same count++ * would mint the same id, so each session adds a random tag of its own.++ */let idCounter = 0++const SESSION_TAG = Math.random().toString(36).slice(2, 6).padEnd(4, '0')export const newId = (prefix: string): string =>-- `${prefix}-${Date.now().toString(36)}-${(idCounter++).toString(36)}`++ `${prefix}-${Date.now().toString(36)}${SESSION_TAG}-${(idCounter++).toString(36)}`export interface Placeable {name: string@@@ -75,7 +75,9 @@ Already here:top-down world can also look drawn rather than modelled.7. **The instant-play funnel.** `/play/<game>` already opens with no download and as a guest. To add:- campaign landing links with attribution (plan T22);-- - a first load kept under about 8 MB for 3D and the casual budget for 2D;++ - a first load kept under about 8 MB for 3D and the casual budget for 2D (measured 2026-10-27 on production, a fresh++ profile to the character screen: 3.72 MB over 77 responses, 1.62 MB textures and the map, 1.08 MB physics wasm,++ 0.81 MB script; the casual entry is 26.5 KB gzip, under its 60 KB budget);- an X ads account and pixel, once the owner sets them up (O36).8. **Creators get paid.** Engagement-based payouts in Vibes, in the spirit of Roblox Creator Rewards: play time in a creator's published worlds, from the money Billing actually takes in. This needs the owner's decision on the share and the rules.
@@ -6,7 +6,7 @@
@@ -6,7 +6,7 @@
"runtime": "node 22, TypeScript (tsx), pnpm workspace; Babylon.js (client) + deterministic Rapier physics; PostgreSQL 18 via openvibe-sdk/db (pg, or embedded PGlite in development); Valkey optional",
"runtime": "node 22, TypeScript (tsx), pnpm workspace; Babylon.js (client) + deterministic Rapier physics; PostgreSQL 18 via openvibe-sdk/db (pg, or embedded PGlite in development); Valkey optional",
"port": 8000,
"port": 8000,
"domain": "openvibe.games, play.openvibe.games",
"domain": "openvibe.games, play.openvibe.games",
- "contracts": "openvibe-contracts v0.209.0, openvibe-sdk v0.62.0, openvibe-shared v4.9.0, openvibe-publishing v1.4.0 (apps/server/package.json)",
+ "contracts": "openvibe-contracts v0.214.0, openvibe-sdk v0.65.0, openvibe-shared v4.15.2, openvibe-publishing v1.4.0 (apps/server/package.json)",
"capabilities": [
"capabilities": [
"games.mod.manage",
"games.mod.manage",
"games.mod.read",
"games.mod.read",
@@ -29,6 +29,8 @@
@@ -29,6 +29,8 @@
"Scraplandia and Salvage Rush in one Games process (M5), in separate place and instance registries; server-scored rounds, per-game achievements and all-time/week leaderboards",
"Scraplandia and Salvage Rush in one Games process (M5), in separate place and instance registries; server-scored rounds, per-game achievements and all-time/week leaderboards",
"scores, unlocks and guest adoptions posted to OpenVibe.Play (GAMES_PLAY_URL)",
"scores, unlocks and guest adoptions posted to OpenVibe.Play (GAMES_PLAY_URL)",
"creator worlds: a published world gets its own page (/worlds/<id>) and is in OpenVibe.Search (openvibe-publishing search-feed)",
"creator worlds: a published world gets its own page (/worlds/<id>) and is in OpenVibe.Search (openvibe-publishing search-feed)",
+ "creators make games the way we do: characters belong to each game, remix a world (credited), its own games-quickjs@1 scripts (run when GAMES_CREATOR_SCRIPTS=1), a team of up to 8 editors by invite link, and a top-down (2D) view",
+ "the asset store: builds (pieces placed in the editor) and scripts shared free for anyone's worlds, placed from the editor's Store tab or added from /worlds",
"Steam's featured lists (top sellers, new releases, specials) read from OpenVibe.Sources (GAMES_SOURCES_URL)",
"Steam's featured lists (top sellers, new releases, specials) read from OpenVibe.Sources (GAMES_SOURCES_URL)",
"the casual line (plan T22): packages/casual kit, server economy with ledger and idempotent actions, Vibe Heroes at /play/vibe-heroes (guest play, adoption on sign-in, earned-only summons, gem store; paid products wait for Billing)",
"the casual line (plan T22): packages/casual kit, server economy with ledger and idempotent actions, Vibe Heroes at /play/vibe-heroes (guest play, adoption on sign-in, earned-only summons, gem store; paid products wait for Billing)",
"six achievement rewards granted as free OpenVibe.Inventory items, never sold or traded; GAMES_ITEMS=on/off and GAMES_INVENTORY_URL configure delivery",
"six achievement rewards granted as free OpenVibe.Inventory items, never sold or traded; GAMES_ITEMS=on/off and GAMES_INVENTORY_URL configure delivery",
@@ -41,5 +43,5 @@
@@ -41,5 +43,5 @@
"the OpenVibe Frame from its own pinned copy",
"the OpenVibe Frame from its own pinned copy",
"per-actor limits on capability-boundary writes (openvibe-sdk/limits)"
"per-actor limits on capability-boundary writes (openvibe-sdk/limits)"
],
],
- "updated": "2026-10-23"
+ "updated": "2026-10-27"
}
}
@@ -9,10 +9,15 @@ import type { StaticBody } from '@openvibe/content'
@@ -9,10 +9,15 @@ import type { StaticBody } from '@openvibe/content'
export type Tool = 'terrain' | 'paint' | 'entity' | 'mesh' | 'select' | 'face' | 'light' | 'zone'
export type Tool = 'terrain' | 'paint' | 'entity' | 'mesh' | 'select' | 'face' | 'light' | 'zone'
-/** Session-stable id generator for map objects (never array positions). */
+/**
+ * Session-stable id generator for map objects (never array positions). The time and counter alone repeat across
+ * sessions: two editors on one map (collaboration, or a team) placing in the same millisecond with the same count
+ * would mint the same id, so each session adds a random tag of its own.
+ */
let idCounter = 0
let idCounter = 0
+const SESSION_TAG = Math.random().toString(36).slice(2, 6).padEnd(4, '0')
export const newId = (prefix: string): string =>
export const newId = (prefix: string): string =>
- `${prefix}-${Date.now().toString(36)}-${(idCounter++).toString(36)}`
+ `${prefix}-${Date.now().toString(36)}${SESSION_TAG}-${(idCounter++).toString(36)}`
export interface Placeable {
export interface Placeable {
name: string
name: string
@@ -75,7 +75,9 @@ Already here:
@@ -75,7 +75,9 @@ Already here:
top-down world can also look drawn rather than modelled.
top-down world can also look drawn rather than modelled.
7. **The instant-play funnel.** `/play/<game>` already opens with no download and as a guest. To add:
7. **The instant-play funnel.** `/play/<game>` already opens with no download and as a guest. To add:
- campaign landing links with attribution (plan T22);
- campaign landing links with attribution (plan T22);
- - a first load kept under about 8 MB for 3D and the casual budget for 2D;
+ - a first load kept under about 8 MB for 3D and the casual budget for 2D (measured 2026-10-27 on production, a fresh
+ profile to the character screen: 3.72 MB over 77 responses, 1.62 MB textures and the map, 1.08 MB physics wasm,
+ 0.81 MB script; the casual entry is 26.5 KB gzip, under its 60 KB budget);
- an X ads account and pixel, once the owner sets them up (O36).
- an X ads account and pixel, once the owner sets them up (O36).
8. **Creators get paid.** Engagement-based payouts in Vibes, in the spirit of Roblox Creator Rewards: play time in a creator's published worlds, from the money Billing actually takes in. This needs the owner's decision on the share and the rules.
8. **Creators get paid.** Engagement-based payouts in Vibes, in the spirit of Roblox Creator Rewards: play time in a creator's published worlds, from the money Billing actually takes in. This needs the owner's decision on the share and the rules.