@homie-rocks/studio 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -1
- package/README.md +361 -22
- package/assets/animate.ts +16 -6
- package/assets/assets.ts +14 -3
- package/assets/render-page.ts +10 -2
- package/assets/safety.mjs +7 -1
- package/bin/homie-studio.mjs +142 -123
- package/lib/art-cli.mjs +61 -18
- package/lib/art-tools.mjs +53 -10
- package/lib/asset-check.mjs +249 -46
- package/lib/asset-import.mjs +11 -5
- package/lib/asset-manifest.mjs +128 -51
- package/lib/build.mjs +239 -72
- package/lib/characters.mjs +119 -20
- package/lib/check.mjs +110 -7
- package/lib/chrome.mjs +11 -0
- package/lib/clips.mjs +54 -0
- package/lib/cloudflare.mjs +127 -8
- package/lib/codex.mjs +6 -0
- package/lib/collision.mjs +245 -0
- package/lib/decisions.mjs +2 -2
- package/lib/demo.mjs +16 -4
- package/lib/deploy-state.mjs +166 -0
- package/lib/dev.mjs +430 -0
- package/lib/directory.mjs +116 -5
- package/lib/doctor.mjs +143 -16
- package/lib/feedback.mjs +3 -2
- package/lib/handoff.mjs +2 -6
- package/lib/library.mjs +1 -1
- package/lib/mcp-tools.mjs +36 -35
- package/lib/mcp.mjs +1 -1
- package/lib/net.mjs +81 -2
- package/lib/node-version.mjs +40 -0
- package/lib/office.mjs +6 -6
- package/lib/optimise.mjs +39 -4
- package/lib/parts-build.mjs +169 -0
- package/lib/parts-cli.mjs +104 -0
- package/lib/parts-store.mjs +342 -0
- package/lib/parts-tools.mjs +92 -0
- package/lib/parts.mjs +693 -0
- package/lib/perf.mjs +131 -31
- package/lib/port-check.mjs +40 -6
- package/lib/preview.mjs +77 -0
- package/lib/routes.mjs +132 -0
- package/lib/scaffold.mjs +88 -22
- package/lib/shoot.mjs +307 -0
- package/lib/site.mjs +1 -2
- package/lib/stage.mjs +118 -0
- package/lib/studio.mjs +0 -66
- package/lib/style-board.mjs +49 -6
- package/lib/template-history.json +101 -0
- package/lib/trailer.mjs +47 -0
- package/lib/typecheck.mjs +107 -0
- package/mcp/ui/lineup.js +3 -3
- package/mcp/ui/rights.js +1 -3
- package/netplay/NETPLAY.md +424 -16
- package/netplay/netplay.ts +756 -40
- package/package.json +10 -1
- package/parts/PARTS.md +163 -0
- package/port/index.ts +8 -2
- package/port/personas.ts +275 -0
- package/port/powerups.ts +357 -0
- package/port/probe.ts +38 -2
- package/port/room.ts +103 -19
- package/site/SITE.md +102 -20
- package/starters/ember-vale/index.html +1 -1
- package/starters/ember-vale/src/main.ts +3 -1
- package/starters/gem-rush/index.html +1 -1
- package/starters/gem-rush/src/main.ts +13 -6
- package/starters/gem-rush-3d/assets/RIGHTS.md +0 -24
- package/starters/gem-rush-3d/assets/manifest.json +0 -24
- package/starters/gem-rush-3d/index.html +1 -1
- package/starters/gem-rush-3d/src/main.ts +15 -5
- package/starters/hero-rush-3d/assets/RIGHTS.md +0 -19
- package/starters/hero-rush-3d/assets/manifest.json +0 -19
- package/starters/hero-rush-3d/index.html +1 -1
- package/starters/hero-rush-3d/src/main.ts +15 -5
- package/worker/arrival.mjs +4 -1
- package/worker/discover.mjs +11 -25
- package/worker/index.mjs +142 -62
- package/worker/license.mjs +45 -41
- package/worker/office-page.mjs +0 -4
- package/worker/office-schema.mjs +6 -0
- package/worker/office.mjs +19 -23
- package/worker/pages.mjs +141 -23
- package/worker/parts.mjs +234 -0
- package/worker/room.mjs +157 -14
- package/worker/schema.mjs +6 -8
- package/worker/seats.mjs +71 -0
- package/worker/site.mjs +51 -53
- package/worker/version.mjs +1 -1
- package/lib/remix-assets.mjs +0 -84
package/site/SITE.md
CHANGED
|
@@ -17,14 +17,21 @@ and every game gets a landing page. Anything the studio puts in `site/` wins.
|
|
|
17
17
|
|
|
18
18
|
A section with nothing in it has no tab, and its address answers 404. Every page ends with a
|
|
19
19
|
"Made with Homie" link to https://homie.rocks/studio/. studio.json may add `"tagline"` (one line, on Home and in
|
|
20
|
-
the feeds)
|
|
20
|
+
the feeds), `"site": { "featured": "<game id>" }` (the game on Home; otherwise the first with its own footage) and
|
|
21
|
+
`"site": { "order": ["<game id>", "<game id>"] }`: **the order of the games** in every list (Home's cards, the
|
|
22
|
+
Games page, `/api/games`, `/sitemap.xml`, `/llms.txt` and `/.well-known/homie-studio.json`). The
|
|
23
|
+
games it names come first, as it names them; every other game follows by id, which is the order all of them had
|
|
24
|
+
before. An id that is not one of the studio's games is skipped, and the build says so. Without `featured`, Home's
|
|
25
|
+
hero is still the first game with footage, now looked for in that order.
|
|
21
26
|
|
|
22
27
|
Every card (Home, Games, Rooms, a post's), every live room's row and the directory's manifest show a game's
|
|
23
28
|
**landing still**: `hero/wide.jpg` (or `landing.hero.image`), else a trailer's poster, else game.json's `cover`.
|
|
24
29
|
|
|
25
30
|
## What the homie.rocks hub reads
|
|
26
31
|
|
|
27
|
-
`/.well-known/homie-studio.json` is the studio's manifest: its games (each with its landing still
|
|
32
|
+
`/.well-known/homie-studio.json` is the studio's manifest: its games (in the site's order, each with its landing still
|
|
33
|
+
as `cover`, and `build`: `{ "hash", "bundle" }`, the digest `homie-studio build` printed for the game that is live
|
|
34
|
+
and the address of the bundle its page loads; [The build](#the-build)),
|
|
28
35
|
songs (each with a `cover`), videos (each with a `poster`), the latest posts, and `rooms`, the address of
|
|
29
36
|
`/api/rooms`, so the hub's Rooms page lists this studio's public rooms. With studio.json `"stats": { "share": true }`
|
|
30
37
|
(`homie-studio stats share on`) it also says "played this week": `played` for the whole studio and each game's own
|
|
@@ -73,26 +80,41 @@ Made from the game's own files, nothing invented:
|
|
|
73
80
|
`games/<id>/hero/` by the house brands' names (`wide.mp4` and `tall.mp4`, their AV1 cuts `wide.av1.mp4` and
|
|
74
81
|
`tall.av1.mp4`, stills `wide.jpg` and `tall.jpg`); a trailer in `videos/manifest.json` whose `for.game` is the
|
|
75
82
|
game (its 16:9 `video`, 9:16 `vertical` and `poster`). A loop of 8 to 15 s under 3 MB each, muted, plays best.
|
|
83
|
+
|
|
84
|
+
**The files, exactly** (all in `games/<id>/hero/`, every one optional; `homie-studio build` names the first two
|
|
85
|
+
when a landing has neither picture nor footage):
|
|
86
|
+
|
|
87
|
+
| File | Shape | What it is |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `wide.jpg` | 16:9, 1280×720 or larger | The still a computer, a TV and every card show (also `.webp`, `.png`, `.avif`) |
|
|
90
|
+
| `tall.jpg` | 9:16, 720×1280 | The still an upright phone shows; without it the wide one is cropped |
|
|
91
|
+
| `wide.mp4` | 16:9, 1280×720 to 1600×900 | Footage over the still: silent, 8 to 15 s, under 3 MB (also `.webm`) |
|
|
92
|
+
| `tall.mp4` | 9:16, 720×1280 | The same for an upright phone |
|
|
93
|
+
| `wide.av1.mp4`, `tall.av1.mp4` | as above | AV1 cuts, offered first to a browser that plays them |
|
|
94
|
+
|
|
95
|
+
The shapes are what fills the screen without waste, not a rule: any size is shown, cropped to fill
|
|
96
|
+
(`landing.hero.focus` says which part to keep). One file is 25 MiB at most. In the built site they are served
|
|
97
|
+
at `/games/<id>/_landing/<file>` (a static game's, which copies its whole folder, at `/games/<id>/hero/<file>`);
|
|
98
|
+
`/api/games` says each exactly, as `games[].landing.hero` (`wide`, `tall`, `wideImage`, `tallImage`).
|
|
76
99
|
- **The pitch** (`landing.pitch`, else the blurb), a big **Play** button that drops into a public room at once,
|
|
77
100
|
and the live line ("3 players playing right now", refreshed every 15 s from `/<id>/live`).
|
|
78
101
|
- **Phone, computer, TV**: the controls for each (`landing.controls`, else `credits.json` `controls`), a code a
|
|
79
102
|
phone scans to play, and how to put the game on a TV (`/<id>/tv` shows the room with its own join code).
|
|
80
103
|
- **Live rooms**, each with Join. When studio.json shares its stats (`stats.share`), also "played this week".
|
|
81
104
|
- **How to play**: `landing.about`, `landing.howToPlay` (a few lines), the controls, the room facts.
|
|
82
|
-
- **Credits**: the studio and `landing.credits` (`[{ "role", "name", "url" }]`); for a
|
|
83
|
-
<game> by <studio>" linked to the original's page (game.json `remixOf
|
|
105
|
+
- **Credits**: the studio and `landing.credits` (`[{ "role", "name", "url" }]`); for a game that was made from another
|
|
106
|
+
studio's, "Based on <game> by <studio>" linked to the original's page (game.json `remixOf`; it is also
|
|
84
107
|
under the game's name in the hero); for a port, the original, its author and licence and every part inside it
|
|
85
108
|
(`credits.json`, as the port skill writes it), with the full licence texts on `/<id>/credits`; Homie's open
|
|
86
|
-
engine; and the
|
|
87
|
-
- **Make a game like this**: the two commands that install the Homie plugin and the words to say. When the game
|
|
88
|
-
shares its source (the default; `"share": { "source": false }` keeps it closed, and the owner's Remixable
|
|
89
|
-
switch withdraws it) and its licence allows remixing, the words remix it from `/games/<id>/source.json`, and
|
|
90
|
-
the button goes to `https://homie.rocks/studio/?remix=<that address>`.
|
|
109
|
+
engine; and the licence the game names for itself, when it names one.
|
|
91
110
|
|
|
92
|
-
A game's licence is game.json `"license"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
A game's licence is game.json `"license"`: an SPDX identifier (`"MIT"`, `"CC-BY-4.0"`), as the word or as
|
|
112
|
+
`{ "spdx": "MIT" }`. It is a statement about the game, said in its credits, its structured data and `/llms.txt`; a
|
|
113
|
+
game that names none says nothing. It offers nobody the game's source: no game is handed over whole. Games build on
|
|
114
|
+
each other through parts, the pieces a studio chooses to share (`parts/PARTS.md`; a game with shared parts gets a
|
|
115
|
+
"Parts from this game" band, and the studio a `/parts/` page). Remix was retired: the settings it had (`"remix"`,
|
|
116
|
+
`"share"`, `landing.make`, the licence words `"remix-with-credit"`, `"remix-freely"` and `"no-remix"`) are ignored
|
|
117
|
+
with one build note, and `/games/<id>/source.json` answers 410.
|
|
96
118
|
|
|
97
119
|
game.json's `landing` block, every key optional:
|
|
98
120
|
|
|
@@ -161,12 +183,74 @@ atproto later. `/.well-known/homie-studio.json` lists the latest posts for the h
|
|
|
161
183
|
| `site/theme.json` | The tokens every page uses: `bg`, `fg`, `accent`, `glow`, `panel`, `accentInk` (colours: `#hex`, `rgb()`, `hsl()`, `oklch()`), `display`, `text`, `mono` (font lists), `fonts` (`[{ "family", "src": "/fonts/x.woff2", "weight": "400 800" }]`, files in `site/public`), `radius` (0 to 40), `mark` (a logo), `icon`, `social` (the share picture), `wordmark`, `uppercase: false`, `scheme: "light"`. Or `palette`: neon, dock, gold, acid, ember, orchid, tide, candy. A value that is not what it should be is dropped, with a warning. |
|
|
162
184
|
| `site/theme.css` | CSS after the site's own, on every generated page: restyle anything. |
|
|
163
185
|
| `site/partials/<name>.html` | A piece of every generated page: `head` (in `<head>`), `header` (the top line and its tabs), `footer` (the "Made with Homie" footer), `home` (a band on Home), `game` (a band on every landing), `game-<id>` (a band on one), `post` (after a post). `{{studio.name}}`, `{{game.name}}`, `{{game.id}}`, `{{game.play}}`, `{{year}}` are filled in. A band partial sits in one of the page's bands, unless it is its own `<section class="band">`. |
|
|
164
|
-
| `site/pages/<path>/index.html` (or `site/pages/<path>.html`) | A whole page at `/<path>/`, served as it is, instead of the generated one (`site/pages/index.html` is Home, `site/pages/<id>/index.html` a game's landing) or beside them (`/about/`). It may borrow the site's parts: `<!-- homie:style -->`, `<!-- homie:header -->`, `<!-- homie:footer -->`, `<!-- homie:script -->`,
|
|
186
|
+
| `site/pages/<path>/index.html` (or `site/pages/<path>.html`) | A whole page at `/<path>/`, served as it is, instead of the generated one (`site/pages/index.html` is Home, `site/pages/<id>/index.html` a game's landing) or beside them (`/about/`). It may borrow the site's parts: `<!-- homie:style -->`, `<!-- homie:header -->`, `<!-- homie:footer -->`, `<!-- homie:script -->`, in its `<head>` `<!-- homie:schema -->` (the structured data the generated page there would carry: Home's, a landing's, else the studio's Organization), and `<!-- homie:home-hero -->` (Home's generated hero for the featured game: its footage or art, title, pitch, Play and the live line) or `<!-- homie:home-hero <id> -->` (the same for the game it names), so a Home of the studio's own never writes a hero by hand. The rooms, the game files, the API and the owner's pages are never a page's. |
|
|
165
187
|
| `site/public/` | Files served as they are at the same path: fonts, a logo, hero footage, a page's pictures. A `robots.txt`, `sitemap.xml`, `llms.txt` or `llms-full.txt` here replaces the one the site makes. |
|
|
166
188
|
| `site/src/worker.mjs` | The Worker. A studio that keeps a whole brand site of its own (with its own routes) wraps the template's Worker here, as the house brands do; everything it does not answer goes to the template. |
|
|
167
189
|
|
|
168
190
|
A studio with its own landing in `site/` keeps it: the template never replaces what the studio made.
|
|
169
191
|
|
|
192
|
+
**A Home of your own, with the generated hero.** `site/pages/index.html` replaces Home. To keep the hero the site
|
|
193
|
+
makes and change only what is under it (or only which game it shows), borrow it:
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
197
|
+
<title>Night Owls</title><!-- homie:style --><!-- homie:schema --></head>
|
|
198
|
+
<body><!-- homie:header -->
|
|
199
|
+
<main><!-- homie:home-hero crown-thief -->
|
|
200
|
+
<section class="band"><div class="band-in"><h2>Whatever this studio wants here</h2></div></section></main>
|
|
201
|
+
<!-- homie:footer --><!-- homie:script --></body></html>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The marker needs `<!-- homie:style -->` (the hero's CSS) and `<!-- homie:script -->` (its live line refreshes).
|
|
205
|
+
A game that is private, invite-only or not this studio's leaves nothing there. A page that does want a game's
|
|
206
|
+
hero files by address reads them from `/api/games` (`games[].landing.hero`); for a bundled game they are
|
|
207
|
+
`/games/<id>/_landing/wide.jpg`, `tall.jpg`, `wide.mp4` and `tall.mp4`, as the table under
|
|
208
|
+
[A game's landing](#a-games-landing-id) says. On the generated Home, `"site": { "featured": "<id>" }` already
|
|
209
|
+
picks the hero's game.
|
|
210
|
+
|
|
211
|
+
## The build
|
|
212
|
+
|
|
213
|
+
`homie-studio build` (`npm run build`) makes `site/dist`, and `homie-studio build <id>` rebuilds one game in it.
|
|
214
|
+
|
|
215
|
+
- **All or nothing.** The site is built in a folder of its own (`.studio/build/`, git-ignored) and put in place
|
|
216
|
+
only when all of it is there. A game that does not build fails the command (exit 1) and leaves `site/dist`
|
|
217
|
+
exactly as it was: never a site without that game for the next deploy to ship. When it is put in place,
|
|
218
|
+
`site/dist` and its folders are not removed and made again: a file that did not change is not touched, a file
|
|
219
|
+
that did is renamed into place in one step, and what the new build no longer has is taken away last. A server
|
|
220
|
+
or a script running from `site/dist` keeps its files across a build.
|
|
221
|
+
- **A bundle named by its content.** A game's code is `games/<id>/assets/main-<HASH>.js`, and the built
|
|
222
|
+
`index.html` names it (write `./assets/main.js` in the game's own `index.html`, as always: the build points it at
|
|
223
|
+
the hashed file). A browser or an edge that kept the last build's bundle is never asked for the new one under the
|
|
224
|
+
old name. `assets/main.js` is still there, one line that imports the hashed bundle, for anything that knew the
|
|
225
|
+
old address; `bundle.json` beside the page says the real file and its chunks.
|
|
226
|
+
- **Code that loads later.** The bundle is ES modules with code splitting: `const scene = await import('./level-2')`
|
|
227
|
+
in a game becomes `assets/chunk-<HASH>.js`, fetched when the game asks for it, from beside the bundle, wherever
|
|
228
|
+
the game is served (the site, its frame at `/<id>/__game/`, `dev`, `preview`, the Game Lab). A 3D game can draw
|
|
229
|
+
its first screen before the rest of its code and three.js add-ons arrive. A game with no `import()` is one file.
|
|
230
|
+
- **What changed.** Each game's line says `new`, `changed` or `unchanged` against the build before, its **build
|
|
231
|
+
hash** (sixteen characters over every file of the game, the same digest `homie-studio perf` names a build by).
|
|
232
|
+
`site/dist/_site/build.json` keeps it for whatever runs next (`{ "v":
|
|
233
|
+
1, "at", "commit", "games": { "<id>": { "hash", "bundle", "chunks", "changed" } } }`), and
|
|
234
|
+
the live site says each game's `build.hash` in `/.well-known/homie-studio.json`: "is the live game the one I
|
|
235
|
+
built?" is that against this, with no file to fetch and no edge cache to wait out.
|
|
236
|
+
- **`build --types`** checks the games' TypeScript first (the build itself only strips types, so a type error
|
|
237
|
+
ships otherwise). It uses the studio's own `typescript` (a new studio's `package.json` asks for it;
|
|
238
|
+
`npm install --save-dev typescript` in an older one; the toolkit does not depend on it), reads a game's own
|
|
239
|
+
`tsconfig.json` when it has one, else checks its entry and what that imports the way the build reads them
|
|
240
|
+
(ES2022, a browser, strict). A type error in a game's own files stops the build before anything is built;
|
|
241
|
+
errors in a package the game imports as source are counted and said, never fatal.
|
|
242
|
+
- **`homie-studio preview <id> [--port 8788]`** serves one built game's files and nothing else (no Wrangler, no
|
|
243
|
+
rooms, no database), on this computer only, for a capture, a screenshot or a perf script. It is the page as the
|
|
244
|
+
build made it, with no room to join: the game plays offline with its bots. It prints its address first (one
|
|
245
|
+
line of JSON with `--json`), reads each file when asked, so the next build is what the next reload gets, and
|
|
246
|
+
stops with Ctrl-C.
|
|
247
|
+
- **A 3D game's model budgets.** `createModels()` (`@homie-rocks/studio/assets`) warns in development about any
|
|
248
|
+
model over 1,500 triangles or 300 KB: a small prop's budget. A game whose models are bigger on purpose says so
|
|
249
|
+
once, in game.json: `"assets": { "budgets": { "triangles": 8000, "bytes": 1500000 } }` (per model; `texturePx`
|
|
250
|
+
and `materials` are taken too, and `createModels({ budget })` or a single `load(url, { budget })` still wins).
|
|
251
|
+
The build writes it into the bundle. A game copied from a 3D starter has `"assets": "library"` there, a note that
|
|
252
|
+
only mattered when it was copied: replace it with the object.
|
|
253
|
+
|
|
170
254
|
## The play page
|
|
171
255
|
|
|
172
256
|
**The arrival (0.26.0).** The play page and the big screen never open blank. From the first paint, an arrival
|
|
@@ -338,7 +422,7 @@ schema.org `@graph`:
|
|
|
338
422
|
| --- | --- |
|
|
339
423
|
| Home | `Organization` (the studio: name, address, `site/theme.json` `mark` as its logo, `social` as its image, the tagline) and `WebSite` |
|
|
340
424
|
| `/games/`, `/rooms/` | `BreadcrumbList`, `ItemList` of the public games' landings (the Rooms page's data never carries a live count) |
|
|
341
|
-
| `/<id>/` | `BreadcrumbList`, `VideoGame` co-typed `WebApplication`: name, description, the pitch as `abstract`, its pictures and screenshots, `genre`, `numberOfPlayers` (min and max), `playMode`, `gamePlatform`, the studio as author and publisher, `license` (the
|
|
425
|
+
| `/<id>/` | `BreadcrumbList`, `VideoGame` co-typed `WebApplication`: name, description, the pitch as `abstract`, its pictures and screenshots, `genre`, `numberOfPlayers` (min and max), `playMode`, `gamePlatform`, the studio as author and publisher, `license` (the licence the game names, linked to its SPDX page; left out when it names none), `isBasedOn` (a port's original), `trailer` (a `VideoObject`), `datePublished` and `dateModified`, a `PlayAction`, and one free-to-play `Offer` (price 0) |
|
|
342
426
|
| `/<id>/credits`, `/<id>/servers/`, a server's page | `BreadcrumbList` |
|
|
343
427
|
| `/music/`, `/music/<slug>/` | `MusicAlbum` (every song names one album) or an `ItemList`; `MusicRecording` (`byArtist` the studio, its duration, its `AudioObject`, its cover, `inAlbum`, `musicalKey`, its date) |
|
|
344
428
|
| `/videos/`, `/videos/<slug>/` | `ItemList`; `VideoObject` (`thumbnailUrl`, `uploadDate`, `duration`, `contentUrl`: the file at its own address, from R2 or the site) |
|
|
@@ -374,15 +458,13 @@ any property schema.org does not put on that type. A whole block of the owner's
|
|
|
374
458
|
- `/sitemap.xml`: Home, Games and each landing (and its credits), Rooms, Music, Videos, Posts and every page in
|
|
375
459
|
`site/pages`, with `lastmod` only where a real date says when it changed.
|
|
376
460
|
- `/llms.txt`, following the llms.txt convention (an H1, a `>` summary, then `##` sections of links): what the
|
|
377
|
-
studio is; each game with its pitch, players, rounds, Play, Watch and the big screen
|
|
378
|
-
|
|
379
|
-
`game_remix` tool, or `homie-studio game remix <source> --id <new-id>`); songs; videos; posts with their Atom and
|
|
461
|
+
studio is; each game with its pitch, players, rounds, Play, Watch and the big screen, the licence it names and
|
|
462
|
+
the game it was based on (when it has either); songs; videos; posts with their Atom and
|
|
380
463
|
JSON feeds; the studio's own pages (a changelog among them); and homie.rocks's own llms.txt.
|
|
381
464
|
- `/llms-full.txt`: the same, with each game's whole description, how to play, controls and credits, and every
|
|
382
465
|
post's text.
|
|
383
466
|
|
|
384
|
-
|
|
385
|
-
allows it, as for the directory. They are cached for five minutes. A file of the studio's own in `site/public` wins.
|
|
467
|
+
They are cached for five minutes. A file of the studio's own in `site/public` wins.
|
|
386
468
|
|
|
387
469
|
## Headers
|
|
388
470
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Ember Vale</title>
|
|
7
7
|
<link rel="icon" href="data:,">
|
|
8
8
|
<style>
|
|
9
|
-
html, body { margin: 0; height: 100%; background: #0b0f0a; overflow: hidden; overscroll-behavior: none; -webkit-user-select: none; user-select: none; font: 15px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; color: #f3ead2; }
|
|
9
|
+
html, body { margin: 0; height: 100%; background: #0b0f0a; overflow: hidden; overscroll-behavior: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; font: 15px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; color: #f3ead2; }
|
|
10
10
|
canvas { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
|
|
11
11
|
.ui { position: fixed; z-index: 3; }
|
|
12
12
|
.pill { left: calc(12px + env(safe-area-inset-left)); top: calc(86px + env(safe-area-inset-top)); display: flex; gap: 6px; }
|
|
@@ -1229,7 +1229,9 @@ exposePort(net, {
|
|
|
1229
1229
|
size: R,
|
|
1230
1230
|
score: () => { const s = room.mySeat(); return room.view().find((b) => b.seat === s && !b.bot)?.score ?? null; },
|
|
1231
1231
|
busy: () => !ui.idle(),
|
|
1232
|
-
|
|
1232
|
+
// `alive` is read by name by the playtest (port/probe.ts PortExtra): a downed hero is waiting to stand up again, and a
|
|
1233
|
+
// press that moves nothing then is not a broken control.
|
|
1234
|
+
extra: { alive: () => !((myViewBody()?.flags ?? 0) & DOWN), level: () => hero?.level ?? 0, frames: () => frames, saves: () => saves.status().mode },
|
|
1233
1235
|
});
|
|
1234
1236
|
|
|
1235
1237
|
void net.ready.then(() => { const b = room.mine(); if (b) { me.x = b.x; me.y = b.y; me.has = true; } });
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Gem Rush</title>
|
|
7
7
|
<link rel="icon" href="data:,">
|
|
8
8
|
<style>
|
|
9
|
-
html, body { margin: 0; height: 100%; background: #04060c; overflow: hidden; overscroll-behavior: none; -webkit-user-select: none; user-select: none; }
|
|
9
|
+
html, body { margin: 0; height: 100%; background: #04060c; overflow: hidden; overscroll-behavior: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
|
|
10
10
|
canvas { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
|
|
11
11
|
</style>
|
|
12
12
|
</head>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
*
|
|
37
37
|
* Canvas 2D on purpose: the point is the contract, in ~700 readable lines.
|
|
38
38
|
*/
|
|
39
|
-
import { createNetplay, Roster, q, lerp, capMove, PALETTE, AI_MARK, type RoleChange, type RoundInfo, type RoundResult, type Skill, type Slot, type Snapshot } from '@homie-rocks/studio/netplay';
|
|
39
|
+
import { createNetplay, guardGestures, Roster, q, lerp, capMove, PALETTE, AI_MARK, type RoleChange, type RoundInfo, type RoundResult, type Skill, type Slot, type Snapshot } from '@homie-rocks/studio/netplay';
|
|
40
40
|
// The port toolkit: its probe (what `homie-studio port check` reads for the owner tests, and sandbox + audio shims),
|
|
41
41
|
// and a flat world on every screen (port/view.ts: the camera, and name labels that never pile up).
|
|
42
42
|
import { BUBBLE_FONT, createBubbles, createLabels, exposePort, fitView, paintBubbles, type BubbleIn, type BubbleOut, type LabelIn, type LabelOut } from '@homie-rocks/studio/port';
|
|
@@ -82,7 +82,7 @@ interface Body extends Knock { slot: number; seat: number | null; name: string;
|
|
|
82
82
|
interface Gem { id: number; x: number; y: number }
|
|
83
83
|
/** Slow state, on the keyed state channel (net.state('zone', ...)), not in the 20 Hz snapshot. */
|
|
84
84
|
interface Zone { n: number; x: number; y: number; r: number; until: number }
|
|
85
|
-
interface Ckpt { round: RoundInfo; bodies: Body[]; gems: Gem[]; roster: Slot[]; tick: number; gemSeq: number }
|
|
85
|
+
interface Ckpt { round: RoundInfo; bodies: Body[]; gems: Gem[]; roster: Slot[]; tick: number; gemSeq: number; occ?: [number, number][] }
|
|
86
86
|
|
|
87
87
|
/* --------------------------------------------------------------- the net */
|
|
88
88
|
/**
|
|
@@ -93,6 +93,9 @@ interface Ckpt { round: RoundInfo; bodies: Body[]; gems: Gem[]; roster: Slot[];
|
|
|
93
93
|
const MOVEMENT: 'owner' | 'host' = (() => { try { return new URLSearchParams(location.search).get('movement') === 'host' ? 'host' : 'owner'; } catch { return 'owner'; } })();
|
|
94
94
|
// caps: its bots read the dial ('skill'), and its Roster takes an AI's slot for it ('agents': the join passes p.agent).
|
|
95
95
|
const net = createNetplay<Snap, Avatar, Ckpt>({ game: 'gem-rush', maxPlayers: MAX_SLOTS, movement: MOVEMENT, snapshotHz: 20, inputHz: 20, checkpointMs: 1000, caps: ['skill', 'agents'], checkpoint: () => checkpoint() });
|
|
96
|
+
// A touch game guards its own page (NETPLAY.md section 24): a long press on the canvas never selects text or raises
|
|
97
|
+
// the copy/paste callout on a phone, and a touch on it never pans or zooms the page.
|
|
98
|
+
guardGestures({ touch: 'canvas' });
|
|
96
99
|
/** The Roster keeps the server's AI seats (revision 6): the policy is read whenever it fills. */
|
|
97
100
|
const policy = () => net.policy;
|
|
98
101
|
|
|
@@ -208,7 +211,9 @@ function becomeHost(e: RoleChange<Snap, Ckpt>): void {
|
|
|
208
211
|
startRound((e.round?.n ?? 0) + 1);
|
|
209
212
|
}
|
|
210
213
|
// Whoever is connected now is who plays: seats that left during the gap become bots.
|
|
211
|
-
const peers = net.offline ? [{ seat: 0, name: 'You' }] : [...net.peers.values()].filter((p) => p.seat !== null).map((p) => ({ seat: p.seat, name: p.name, agent: p.agent ?? null }));
|
|
214
|
+
const peers = net.offline ? [{ seat: 0, name: 'You' }] : [...net.peers.values()].filter((p) => p.seat !== null).map((p) => ({ seat: p.seat, name: p.name, agent: p.agent ?? null, occ: p.occ ?? null }));
|
|
215
|
+
// `occ` (NETPLAY.md section 25): which stay in its seat each peer's is, so a seat number that changed hands while
|
|
216
|
+
// nobody was hosting is claimed afresh instead of inheriting the last player's body in silence.
|
|
212
217
|
const { claimed } = roster.reconcile(peers);
|
|
213
218
|
syncBodiesFromRoster();
|
|
214
219
|
for (const s of claimed) { const b = bodies.get(s.slot); if (b && b.seat !== mySeat()) hostMoved(b); }
|
|
@@ -225,7 +230,7 @@ function becomeHost(e: RoleChange<Snap, Ckpt>): void {
|
|
|
225
230
|
function restore(e: RoleChange<Snap, Ckpt>): void {
|
|
226
231
|
const ck = e.ckpt?.d ?? null;
|
|
227
232
|
if (ck) {
|
|
228
|
-
roster = Roster.from(ck.roster, { min: MIN_SLOTS, max: MAX_SLOTS, botName, policy });
|
|
233
|
+
roster = Roster.from(ck.roster, { min: MIN_SLOTS, max: MAX_SLOTS, botName, policy }, ck.occ ?? null);
|
|
229
234
|
bodies = new Map(ck.bodies.map((b) => [b.slot, { ...b }]));
|
|
230
235
|
gems = ck.gems.map((g) => ({ ...g }));
|
|
231
236
|
gemSeq = ck.gemSeq;
|
|
@@ -266,6 +271,8 @@ function checkpoint(): Ckpt {
|
|
|
266
271
|
bodies: [...bodies.values()].map((b) => ({ ...b })),
|
|
267
272
|
gems: gems.map((g) => ({ ...g })),
|
|
268
273
|
roster: roster.toJSON(),
|
|
274
|
+
// Whose stay each body is, beside the roster: how the next host tells a player who came back from a new one.
|
|
275
|
+
occ: roster.occupants(),
|
|
269
276
|
tick,
|
|
270
277
|
gemSeq,
|
|
271
278
|
};
|
|
@@ -278,7 +285,7 @@ net.on('role', (e) => {
|
|
|
278
285
|
net.on('join', (p) => {
|
|
279
286
|
if (!hosting || p.seat === null) return;
|
|
280
287
|
// An AI takes a seat kept for AI, a person never does (revision 6: the Roster needs p.agent for that).
|
|
281
|
-
const c = roster.claim(p.seat, p.name, p.agent ? { role: p.agent.role, hands: p.agent.hands } : null);
|
|
288
|
+
const c = roster.claim(p.seat, p.name, p.agent ? { role: p.agent.role, hands: p.agent.hands } : null, p.occ ?? null);
|
|
282
289
|
if (!c) return; // full: they watch
|
|
283
290
|
syncBodiesFromRoster();
|
|
284
291
|
const b = bodies.get(c.slot.slot);
|
|
@@ -1036,7 +1043,7 @@ net.expose({
|
|
|
1036
1043
|
if (!hosting) return false;
|
|
1037
1044
|
const b = [...bodies.values()].find((x) => x.seat === seat);
|
|
1038
1045
|
if (!b) return false;
|
|
1039
|
-
knock(b, b.x < W / 2 ? b.x - 1 : b.x + 1, b.y); // push toward the middle, away from the nearer wall
|
|
1046
|
+
knock(b, b.x < W / 2 ? b.x - 1 : b.x + 1, b.y, -1); // push toward the middle, away from the nearer wall (bumped by nobody)
|
|
1040
1047
|
return true;
|
|
1041
1048
|
},
|
|
1042
1049
|
});
|
|
@@ -15,7 +15,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
15
15
|
- **What:** character (Players/Cat): `public/models/animal-cat.glb`
|
|
16
16
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-cat (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
17
17
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
18
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
19
18
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
20
19
|
|
|
21
20
|
### animal-caterpillar
|
|
@@ -23,7 +22,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
23
22
|
- **What:** character (Players/Caterpillar): `public/models/animal-caterpillar.glb`
|
|
24
23
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-caterpillar (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
25
24
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
26
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
27
25
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
28
26
|
|
|
29
27
|
### animal-chick
|
|
@@ -31,7 +29,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
31
29
|
- **What:** character (Players/Chick): `public/models/animal-chick.glb`
|
|
32
30
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-chick (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
33
31
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
34
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
35
32
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
36
33
|
|
|
37
34
|
### animal-crab
|
|
@@ -39,7 +36,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
39
36
|
- **What:** character (Players/Crab): `public/models/animal-crab.glb`
|
|
40
37
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-crab (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
41
38
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
42
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
43
39
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
44
40
|
|
|
45
41
|
### animal-elephant
|
|
@@ -47,7 +43,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
47
43
|
- **What:** character (Players/Elephant): `public/models/animal-elephant.glb`
|
|
48
44
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-elephant (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
49
45
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
50
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
51
46
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
52
47
|
|
|
53
48
|
### animal-fox
|
|
@@ -55,7 +50,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
55
50
|
- **What:** character (Players/Fox): `public/models/animal-fox.glb`
|
|
56
51
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-fox (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
57
52
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
58
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
59
53
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
60
54
|
|
|
61
55
|
### animal-panda
|
|
@@ -63,7 +57,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
63
57
|
- **What:** character (Players/Panda): `public/models/animal-panda.glb`
|
|
64
58
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-panda (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
65
59
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
66
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
67
60
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
68
61
|
|
|
69
62
|
### animal-pig
|
|
@@ -71,7 +64,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
71
64
|
- **What:** character (Players/Pig): `public/models/animal-pig.glb`
|
|
72
65
|
- **From:** from the Homie starter library: Kenney Cube Pets, animal-pig (https://kenney.nl/assets/cube-pets); library, in game (src/main.ts)
|
|
73
66
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
74
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
75
67
|
- **Notes:** From the Homie starter library (kenney-cube-pets); the pack's own licence text: licenses/kenney-cube-pets.txt. `game new` fetches the file; the repository holds no models.
|
|
76
68
|
|
|
77
69
|
### bush
|
|
@@ -79,7 +71,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
79
71
|
- **What:** prop (Places/Bush): `public/models/bush.glb`
|
|
80
72
|
- **From:** from the Homie starter library: Kenney Nature Kit, tree-fat (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
81
73
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
82
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
83
74
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
84
75
|
|
|
85
76
|
### campfire
|
|
@@ -87,7 +78,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
87
78
|
- **What:** prop (Places/Campfire): `public/models/campfire.glb`
|
|
88
79
|
- **From:** from the Homie starter library: Kenney Nature Kit, campfire-stones (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
89
80
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
90
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
91
81
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
92
82
|
|
|
93
83
|
### fence
|
|
@@ -95,7 +85,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
95
85
|
- **What:** kit (Places/Fence): `public/models/fence.glb`
|
|
96
86
|
- **From:** from the Homie starter library: Kenney Nature Kit, fence-simple (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
97
87
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
98
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
99
88
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
100
89
|
|
|
101
90
|
### firewood
|
|
@@ -103,7 +92,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
103
92
|
- **What:** prop (Places/Firewood): `public/models/firewood.glb`
|
|
104
93
|
- **From:** from the Homie starter library: Kenney Nature Kit, campfire-logs (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
105
94
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
106
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
107
95
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
108
96
|
|
|
109
97
|
### flower-purple
|
|
@@ -111,7 +99,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
111
99
|
- **What:** prop (Places/Purple flower): `public/models/flower-purple.glb`
|
|
112
100
|
- **From:** from the Homie starter library: Kenney Nature Kit, flower-purple-a (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
113
101
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
114
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
115
102
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
116
103
|
|
|
117
104
|
### flower-red
|
|
@@ -119,7 +106,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
119
106
|
- **What:** prop (Places/Red flower): `public/models/flower-red.glb`
|
|
120
107
|
- **From:** from the Homie starter library: Kenney Nature Kit, flower-red-a (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
121
108
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
122
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
123
109
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
124
110
|
|
|
125
111
|
### flower-yellow
|
|
@@ -127,7 +113,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
127
113
|
- **What:** prop (Places/Yellow flower): `public/models/flower-yellow.glb`
|
|
128
114
|
- **From:** from the Homie starter library: Kenney Nature Kit, flower-yellow-a (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
129
115
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
130
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
131
116
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
132
117
|
|
|
133
118
|
### gem
|
|
@@ -135,7 +120,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
135
120
|
- **What:** prop (Items/Gem): `public/models/gem.glb`
|
|
136
121
|
- **From:** from the Homie starter library: Kenney Platformer Kit, jewel (https://kenney.nl/assets/platformer-kit); library, in game (src/main.ts)
|
|
137
122
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
138
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
139
123
|
- **Notes:** From the Homie starter library (kenney-platformer-kit); the pack's own licence text: licenses/kenney-platformer-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
140
124
|
|
|
141
125
|
### grass
|
|
@@ -143,7 +127,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
143
127
|
- **What:** prop (Places/Grass): `public/models/grass.glb`
|
|
144
128
|
- **From:** from the Homie starter library: Kenney Nature Kit, grass-leafs-large (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
145
129
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
146
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
147
130
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
148
131
|
|
|
149
132
|
### log
|
|
@@ -151,7 +134,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
151
134
|
- **What:** prop (Places/Log seat): `public/models/log.glb`
|
|
152
135
|
- **From:** from the Homie starter library: Kenney Nature Kit, log-large (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
153
136
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
154
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
155
137
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
156
138
|
|
|
157
139
|
### mushrooms
|
|
@@ -159,7 +141,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
159
141
|
- **What:** prop (Places/Mushrooms): `public/models/mushrooms.glb`
|
|
160
142
|
- **From:** from the Homie starter library: Kenney Nature Kit, mushroom-red-group (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
161
143
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
162
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
163
144
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
164
145
|
|
|
165
146
|
### rock
|
|
@@ -167,7 +148,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
167
148
|
- **What:** prop (Places/Rock): `public/models/rock.glb`
|
|
168
149
|
- **From:** from the Homie starter library: Kenney Nature Kit, stone-large-d (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
169
150
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
170
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
171
151
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
172
152
|
|
|
173
153
|
### stone
|
|
@@ -175,7 +155,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
175
155
|
- **What:** prop (Places/Standing stone): `public/models/stone.glb`
|
|
176
156
|
- **From:** from the Homie starter library: Kenney Nature Kit, stone-tall-c (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
177
157
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
178
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
179
158
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
180
159
|
|
|
181
160
|
### tree-oak
|
|
@@ -183,7 +162,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
183
162
|
- **What:** prop (Places/Oak tree): `public/models/tree-oak.glb`
|
|
184
163
|
- **From:** from the Homie starter library: Kenney Nature Kit, tree-oak (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
185
164
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
186
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
187
165
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
188
166
|
|
|
189
167
|
### tree-pine
|
|
@@ -191,7 +169,6 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
191
169
|
- **What:** prop (Places/Pine): `public/models/tree-pine.glb`
|
|
192
170
|
- **From:** from the Homie starter library: Kenney Nature Kit, tree-pine-round-a (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
193
171
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
194
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
195
172
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|
|
196
173
|
|
|
197
174
|
### tree-round
|
|
@@ -199,5 +176,4 @@ Read on the dates shown. Terms change: read the live page again before publishin
|
|
|
199
176
|
- **What:** prop (Places/Round tree): `public/models/tree-round.glb`
|
|
200
177
|
- **From:** from the Homie starter library: Kenney Nature Kit, tree-default (https://kenney.nl/assets/nature-kit); library, in game (src/main.ts)
|
|
201
178
|
- **Licence:** CC0 1.0 (public domain) (https://creativecommons.org/publicdomain/zero/1.0/); owner: Kenney
|
|
202
|
-
- **A remix:** a remix gets this file (fetched from this studio's site, checked by SHA-256)
|
|
203
179
|
- **Notes:** From the Homie starter library (kenney-nature-kit); the pack's own licence text: licenses/kenney-nature-kit.txt. `game new` fetches the file; the repository holds no models.
|