BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Play-as-you-download for the web: run a game engine in the browser and stream its data from any CDN with HTTP Range requests. Not cloud gaming: no servers, no GPUs, no video.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Play-as-you-download for the web. Run a game engine compiled to WebAssembly in a browser tab, and stream its data from any CDN while it plays. There are no game servers and no data-center GPUs, and nothing is video-encoded. The network carries game data once, then mostly serves cache hits.
▶ Watch the 2-minute explainer (with sound) · Try the demos (best in a current Chromium-based browser, for WebGPU; others fall back to a 2D canvas)
On 6 October 2026 I came across someone running GTA V in a web browser. GTA V takes more than 100 GB on disk, and there it was, playing in a browser tab. I found that fascinating, so I took it apart to see how it worked. It didn't download the game first. It started playing after about 2 GB, and fetched the rest while you played.
Cloud gaming already promises games without installs, but the way it delivers them is a livestream you can control. The game runs on a GPU in a data center, and every frame is encoded and sent to you, for as long as you play.
What if a game worked like a video instead? A video never downloads before it plays: it loads the next few seconds, just before you need them. A game can do the same with its data. It runs on your own device and fetches each level as you reach it, then rebuilds it locally into a smooth, on-device experience. Instead of installing games, you would open them the way you open a video. Imagine Netflix, for games.
| Cloud gaming: a livestream you can control | What if games loaded like a video? |
|---|---|
Fortnite is already heading there. It runs whole games inside one app: Battle Royale, Save the World, LEGO Fortnite,
Festival. You pick one and play, with nothing else to install. And the Unreal Engine 6 teaser (May 2026, the engine
that merges Unreal Engine 5 with UEFN around Verse) showed Rocket League at verse://rocketleague.com, right next to
Fortnite, LEGO and Disney. I think this could be a really interesting model for gaming.
Screenshots: Epic Games (fortnite.com; the teaser frame as captured by Shacknews), shown here for commentary. Portions of the materials used are trademarks and/or copyrighted works of Epic Games, Inc. This project is not affiliated with or endorsed by Epic.
So I built an open-source version for any engine. rangeplay is a clean-room implementation: it contains no code or data from that port, or from GTA V. The demos below run free games: Freedoom, LibreQuake, and a generated world.
| LibreQuake: a 210 MB game, streamed a level at a time |
|---|
| The Quake engine, compiled with Emscripten and brought up to what modern maps need (engine.patch), plays a 4-episode game of 54 maps. Each level downloads when the engine loads it. From an empty cache, the first demo's 9.8 MB level is loaded in 4.1 s with a boot set (19.7 s without), and levels you never visit never download. |
| Freedoom: a complete game | tile-world: a streamed world |
|---|---|
| The unmodified Doom engine, compiled from C with Emscripten, reads its 27.5 MB game through rangeplay. From an empty cache: first frame in 2.9 s (85 s without a boot set), 5 of 2,600 start-up reads waited on the network, and the rest of the game installed in the background. | 144 MB of terrain in 36 archives. Tiles stream in as the camera moves, fetched ahead of it from read hints. The engine starts in 0.6 s on an empty cache, 2.4 s without a boot set, and 0.1 s on a return visit. |
Timings from the dev server's simulated network: 40 ms latency, 3 MB/s per response, HTTP/1.1.
It is the other trade-off. Cloud gaming moves the computer to the data center and streams pixels. rangeplay keeps the computer where it is and streams the game's files.
| Cloud gaming (video streaming) | rangeplay (local execution, streamed data) | |
|---|---|---|
| Where the game runs | A GPU in a data center | The player's device |
| What crosses the network | Video down and input up, every frame, all session | Game data, once; later visits are mostly cache hits |
| What it costs to serve | GPU-hours per concurrent player | CDN bytes per new player or new content |
| Input latency | A network round trip plus encode and decode | Local |
| Device needed | Anything that plays video | A capable CPU/GPU and a current browser |
| First minute | Instant | Engine plus boot set download (tens to hundreds of MB) |
| The game's files | Never leave the server | On the player's device, like any download (this is not DRM) |
Cloud gaming still wins for high-end games on weak devices. rangeplay fits games that can run on the player's hardware but should start from a link: web distribution, demos, back catalogs, user-generated content.
The drawings come from one tldraw board, docs/explainers/rangeplay.tldr: open it in tldraw to see the whole story on one canvas. In detail:
flowchart LR
subgraph CDN["Any static host or CDN"]
M["manifest.json"]
B["bootset.json"]
O["data/xx/<hash><br/>content-addressed, immutable"]
end
subgraph Tab["Player's browser tab (cross-origin isolated)"]
P["Page: host.js<br/>canvas, input"]
E["Engine threads<br/>wasm or JS"]
IO["IO worker<br/>Range fetches, block cache"]
G["GPU worker<br/>WebGPU device"]
S[("OPFS<br/>data.bin + journal.bin")]
end
O -- "HTTP Range" --> IO
B -- "prefetch at load" --> IO
E -- "blocking reads + hints<br/>(shared memory)" --> IO
IO -- "bytes into engine memory" --> E
IO <--> S
E -- "command ring" --> G
P -- "input ring" --> E
G --> C["canvas"]
Atomics.wait) until the IO worker
has put the bytes into the engine's own memory. Native engines need no async rewrite of their file layer.docs/architecture.md explains each decision and its alternatives. docs/protocol.md specifies the shared-memory protocol.
Requires Node 20 or later. There are no dependencies.
npm run demo:build
npm run demo
Then open http://localhost:8080/examples/tile-world/. For Freedoom, run node examples/freedoom/build.js first
(it downloads the game, 24 MB), then open http://localhost:8080/examples/freedoom/. The engine is prebuilt in
examples/freedoom/wasm/.
The dev server adds 40 ms of latency and caps each response at 3 MB/s, so streaming is visible. Use Clear cache to
see a first visit again, and add ?nobootset=1 to see what the boot set saves. npm test runs the test suite;
npm run test:native builds and runs the C protocol test.
fopen (demos played straight from the pak), a palette-lookup GPU handler, an old DMA-style sound mixer
on the audio ring, and bringing a 1996 engine up to what today's maps need.rangeplay is not on npm yet. Install it from a clone (npm install ../rangeplay) to get the rangeplay command and
the rangeplay/* imports, or import src/host.js and src/engine.js by relative path.
1. Pack your data. This hashes every file into dist/data/ and writes dist/manifest.json.
npx rangeplay pack ./gamedata --out ./dist --name my-game
If the game has hundreds of small files (shaders, scripts, configs), add --pack-small 64k: files under 64 KB go into
packs of a few MB, so loading hundreds of them costs a handful of requests instead of one each. In our benchmark, 600
small files loaded in 0.5 s instead of 2.2 s, and the host stored 20 objects instead of 2,001
(architecture.md, "Packs for small files"). rangeplay inspect tells you
when a manifest would gain from it.
2. Start it from the page.
import { start } from 'rangeplay/host';
const game = await start({
canvas: document.querySelector('canvas'),
manifest: './dist/manifest.json',
bootset: './dist/bootset.json', // optional
engine: new URL('./engine-worker.js', import.meta.url), // your engine, as a module worker
gpuHandlers: new URL('./gpu.js', import.meta.url), // your engine's GPU commands
onStats: (s) => console.log(s.bytesFetched, s.store.bytes),
});
3. Read files from the engine. An engine written in JavaScript uses src/engine.js:
import { connect } from 'rangeplay/engine';
const rt = await connect({ heapBytes: 64 << 20 });
const id = rt.files.id('levels/level1.pak');
const buf = rt.heap.alloc(4096);
const n = rt.io.readSync(id, 0, 4096, buf); // blocks this thread until the bytes are in
rt.io.hint(id, 1 << 20, 256 << 10); // "I will read this soon"
A C or C++ engine uses the single header native/rangeplay.h:
int64_t n = rp_read(ctl, file_id, offset, dst, len, 0); /* same protocol, from any pthread */
rp_hint(ctl, file_id, next_offset, next_len, 0);
docs/emscripten.md walks through an Emscripten build, step by step, using the Freedoom port.
Options for real games.
pointerLock: true: a click locks the pointer, for mouse look.fineTimers: true: a workaround for Chrome on Windows, which rounds short Atomics.wait timeouts up to the 15.6 ms
system tick.onStall(info): called with game.debug() if loading stops making progress.game.audio(): the audio ring's level and underruns.game.gpu(): which GPU the game draws with (vendor, architecture, software fallback or not), why it fell back to the
2D canvas if it did, and how many WebGPU errors and lost devices there were. Attach it to bug reports.onGpuLost(info), onGpuRestored(gpu): a lost WebGPU device (a driver reset, a GPU process crash) is replaced and
the GPU handlers' setup() runs again. Handlers that upload resources once must upload them again then.An engine gets an audio ring with connect({ audio: { frames, channels, rate } }) in JavaScript, or rp_audio_* in C.
4. Record a boot set. Load the game with record: true and play the opening. Save
game.takeRecording() as JSON. To have the rest of the game download in the background after the boot set, pass
io: { backgroundFill: ['game.pak'] }. To merge several recordings:
npx rangeplay bootset merge rec1.json rec2.json -o dist/bootset.json
5. Deploy to any static host or CDN that serves byte ranges. (The demo itself is deployed this way: see
vercel.json and scripts/build-site.js.) The page needs cross-origin isolation headers, and
the objects need immutable caching. rangeplay headers <cloudflare|netlify|nginx|caddy|vercel> prints the
configuration for that host; docs/deploying.md has the details.
Check the folder before you upload it, and the host after:
npx rangeplay verify dist
npx rangeplay doctor https://example.com/my-game/
verify checks that every object exists and hashes to its name. doctor checks what makes a game fail to start or
start slowly, and says what to change: isolation headers, byte ranges, an HTML fallback page served instead of data,
compression on the fly, caching, CORS and the boot set. rangeplay mirror <manifest URL> --out <dir> makes a verified,
resumable copy of a published game, to move it to another host.
| Needs | For | Without it |
|---|---|---|
| Cross-origin isolation, SharedArrayBuffer | Engine threads, blocking reads | Does not start (start() explains which headers to set) |
| OffscreenCanvas | Drawing from the GPU worker | Does not start |
| OPFS sync access handles | The persistent cache | In-memory cache, plus the browser's HTTP cache |
| WebGPU | Your engine's renderer | Your handlers decide; the demo falls back to a 2D canvas |
Atomics.waitAsync | Waking the IO and GPU workers | They poll with a short backoff |
| AudioWorklet | Playing the engine's audio ring | Silent |
| Web Locks | One tab owning the cache | No multi-tab protection |
Tested so far: Chromium 152 on Windows (both demos, on WebGPU and on the 2D fallback) and Node 20 to 26 (the test suite). Firefox and Safari are untested; reports are welcome. The browser check tests all of the above on a player's device and makes a report to paste into an issue.
This is version 0.2, and experimental. What is tested:
worker_threads, both stores, 503 storms, stalled
and misbehaving servers, damaged caches, cache reuse across sessions and versions, boot sets and hints, packs.verify on damaged, truncated and missing objects, mirror
resuming interrupted and damaged downloads, doctor on hosts that drop isolation headers, ignore ranges, compress
responses or answer with an HTML fallback page.-Wall -Wextra -Werror.Not done yet:
None of the pieces are new. Emscripten has lazily loaded files, Unity and Godot export to WebAssembly, and consoles have offered "play as you download" for years. rangeplay packages the part each large port ends up rebuilding on its own: an IO path for engine threads that block, a persistent cache, boot sets and read hints, and a GPU worker.
Only ship content you own or have licensed. rangeplay makes a game's files downloadable by design. It is not a protection mechanism.