[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93089":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":16,"rankGlobal":9,"rankLanguage":9,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":14,"starSnapshotCount":14,"syncStatus":12,"lastSyncTime":25,"discoverSource":26},93089,"open-strike","pocket-stack\u002Fopen-strike","pocket-stack","A CS-like FPS on the Pocket runtime family: Pocket3D Rust core, QuickJS gameplay mods, Solid JSX HUD",null,"Rust",65,2,1,0,10,42.43,"MIT License",false,"main",true,[],"2026-07-22 04:02:08","# OpenStrike\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"docs\u002Fhero.jpg\" width=\"820\" alt=\"OpenStrike rendering de_dust in Pocket3D — a wide sunlit desert courtyard with arches, crates and an open sky.\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"docs\u002Fdust2.jpg\" width=\"270\" alt=\"OpenStrike on de_dust2\" \u002F>\n  \u003Cimg src=\"docs\u002Finferno.jpg\" width=\"270\" alt=\"OpenStrike on de_inferno\" \u002F>\n  \u003Cimg src=\"docs\u002Foffice.jpg\" width=\"270\" alt=\"OpenStrike on cs_office\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"docs\u002Fpsp-dust2.png\" width=\"480\" alt=\"OpenStrike running on a Sony PSP — the sunlit de_dust2 courtyard at 480×272, with the JSX HUD and viewmodel\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\u003Cem>A CS-like FPS on classic BSP maps — Pocket3D worlds, a PocketJS JSX HUD, gameplay in TypeScript.\u003Cbr\u002F>\nThe same game runs on desktop (wgpu) and on a real 2004 Sony PSP (sceGu) at a locked 60 fps — bottom shot is the PSP.\u003C\u002Fem>\u003C\u002Fp>\n\nA single-player CS-like FPS built on the **Pocket runtime family**: a Rust\ncore (Pocket3D) simulates and renders; the *product* — round rules, weapon\ntables, difficulty, and the entire HUD — is JavaScript running in an embedded\nQuickJS guest. OpenStrike is the first specialized game runtime of\n[PocketJS](https:\u002F\u002Fgithub.com\u002Fpocket-stack\u002Fpocketjs); the architecture it\ninstantiates is documented in the engine repo's\n[RUNTIMES.md](https:\u002F\u002Fgithub.com\u002Fpocket-stack\u002Fpocketjs\u002Fblob\u002Fmain\u002FRUNTIMES.md).\n\n```\ncrates\u002Fopenstrike-core   the simulation — no_std Rust shared VERBATIM by both\n                         targets (movement, bots, weapons, round state)\ncrates\u002Fopenstrike        the desktop build\n  ├─ pocket3d            wgpu renderer, BSP worlds, collision, skeletal anim\n  ├─ pocket-mod          the QuickJS guest (one realm, one turn per tick)\n  ├─ pocket-ui-wgpu      the `ui` surface — PocketJS, composited as the HUD\n  └─ strike surface      this game's vocabulary (src\u002Fguest.rs)\ncrates\u002Fopenstrike-psp    the PSP build: an EBOOT on pocket3d-gu (sceGu) and\n                         the PocketJS PSP host — same surfaces, same bundle\n\ngame\u002F                    the product bundle (JS\u002FTSX) — runs on BOTH targets\n  ├─ sdk.ts              `strike` SDK: state snapshots, events, commands\n  ├─ rules.ts            the base game as the FIRST MOD: round flow, scoring,\n  │                      weapon + bot tuning\n  └─ hud.tsx             the HUD — a full PocketJS app (Solid + Tailwind)\n\nvendor\u002Fpocketjs          the engine, pinned as a git submodule\n```\n\nEvery tick: the core simulates, publishes a state snapshot + event batch to\nthe guest (`strike.__dispatch`), the HUD frame runs, and the guest's queued\ncommands (`setPhase`, `resetRound`, `configureWeapon`, …) apply back to the\ncore. Facts flow one way, intent flows the other, and the guest never blocks\nthe simulation. Change `game\u002Frules.ts` and you have made a mod — the base\ngame grants itself no privileges a mod wouldn't have.\n\n## Building\n\n```sh\ngit clone --recursive https:\u002F\u002Fgithub.com\u002Fpocket-stack\u002Fopen-strike\ncd open-strike\nbun run setup      # installs the vendored framework deps + solid-js link\nbun run build:ui   # game\u002Fopenstrike.tsx -> dist\u002Fopenstrike.{js,pak}\n```\n\n### Map data\n\nMaps and textures are **not** in this repo (they are Valve-copyrighted game\ndata). Point the game at a directory containing them:\n\n```\n\u003Cmaps-root>\u002F\n├── maps\u002Fde_dust2.bsp  (and friends)\n└── support\u002F*.wad      (cs_dust.wad, halflife.wad, ...)\n```\n\nAny GoldSrc-era (BSP v30) map works; the eight classic CS maps are the\ntested set. `OPENSTRIKE_MAPS` can replace `--maps-dir` below.\n\n### Play\n\n```sh\ncargo run --release -p openstrike -- --maps-dir ~\u002Fpath\u002Fto\u002Fcs-maps\n```\n\n| Input | Action |\n| --- | --- |\n| Mouse | look |\n| WASD | move (Shift = walk) |\n| Space | jump |\n| Left mouse | fire |\n| R | reload |\n| Esc | release\u002Fcapture mouse |\n| F3 | debug overlay |\n| V | noclip fly (debug) |\n\nOptions: `--map de_inferno`, `--bots 5`, `--spawn-t`, `--auto-quit 5`.\n\nRound rules (v0.1, see `game\u002Frules.ts`): eliminate every bot to win; die and\nyou lose. Either way the round resets automatically and the score carries\nover.\n\n## Headless verification\n\nEvery acceptance criterion runs without a window — the renderer draws\noffscreen, input is scripted, the RNG is seeded, and the round\u002Flose scripts\nboot the full QuickJS guest so the *shipped* rules and HUD are what gets\ntested:\n\n```sh\ncargo run --release -p openstrike -- --maps-dir $MAPS --script walk   --screenshot out\u002Fwalk\ncargo run --release -p openstrike -- --maps-dir $MAPS --script model  --screenshot out\u002Fmodel\ncargo run --release -p openstrike -- --maps-dir $MAPS --script combat --screenshot out\u002Fcombat\ncargo run --release -p openstrike -- --maps-dir $MAPS --script round  --screenshot out\u002Fround\ncargo run --release -p openstrike -- --maps-dir $MAPS --script lose   --screenshot out\u002Flose\n```\n\n- `walk` — spawn, run at 250 u\u002Fs, slide along walls without clipping, jump\n  exactly ~45 units, and hold the viewmodel anti-jitter invariant (the gun\n  must ride the interpolated camera, not the raw tick state).\n- `model` — the soldier renders and its clips actually animate.\n- `combat` — aim, fire, tracers\u002Fflash, a bot takes three body shots and dies.\n- `round` — observe bot AI, engage, eliminate all, **win** (scored by the JS\n  rules), and verify the automatic next round. Screenshots include the HUD.\n- `lose` — stand still until the bots win; verify the loss + restart.\n\n## Real PSP hardware\n\nOpenStrike runs on an actual Sony PSP — same simulation, same JS rules, same\nJSX HUD, rendered by the sceGu backend (`pocket3d-gu`). Not a stripped-down\ndemo: the identical `dist\u002Fopenstrike.js` bundle that drives the desktop build\nboots in QuickJS on the handheld. It ships as a proper EBOOT — branded XMB\nicon and backdrop, a main menu that lists every cooked map, and SELECT to\nreturn there mid-round.\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"docs\u002Fpsp-menu.png\" width=\"400\" alt=\"OpenStrike PSP main menu — a two-column map list (all eight CS classics) under the wordmark\" \u002F>\n  \u003Cimg src=\"docs\u002Fpsp-fire.png\" width=\"400\" alt=\"Firing on PSP — muzzle flash and the compact corner HUD\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\u003Cem>Captured from the shipping EBOOT in PPSSPP's software renderer at native 480×272 — the same\ndeterministic backend the byte-exact e2e goldens run on.\u003C\u002Fem>\u003C\u002Fp>\n\n```sh\ngit submodule update --init          # pocketjs + rust-psp + quickjs-rs forks\nbun scripts\u002Fpsp.ts                   # bundle → cook every map → cargo psp EBOOT\nbun scripts\u002Fpsp.ts --package         # + assemble dist\u002FPSP\u002FGAME\u002FOpenStrike (ms0 layout)\nbun scripts\u002Fhw.ts --bench            # launch over PSPLINK; frame times stream back\nbun scripts\u002Fe2e-psp.ts               # deterministic PPSSPP goldens (spawn\u002Fwalk\u002Ffire)\n```\n\nInstall: copy `dist\u002FPSP\u002F` to a Memory Stick root (or the emulator's memstick\ndir) on a homebrew-enabled PSP; OpenStrike appears in the Game menu with its\nicon. The build needs the PSP toolchain from the PocketJS ecosystem\n(`pocket doctor`) plus the CS maps (`OPENSTRIKE_MAPS`).\n\nControls: analog stick moves, `△\u002F✕\u002F□\u002F○` looks, `R` fires, `L` jumps, d-pad\ndown reloads, d-pad up walks, **SELECT** opens the return-to-menu dialog. In\nthe menu, d-pad selects a map and `○` deploys.\n\nMeasured on hardware (333 MHz, `--bench`, scripted dust2 tour): a locked\n60 fps, GE under 30 µs — and combat is flat too (no per-shot hitch: the HUD\nupdates through the framework's imperative hot path, avoiding a reactive\nflush per frame). Cooking bakes lightmaps into vertex colors, keeps WAD\ntextures as swizzled CLUT8 with full mip chains, and ships PVS so the renderer\ndraws only the visible leaves; each `.p3d` is consumed zero-copy, and maps\nload on demand from `maps\u002F` next to the EBOOT into one reused buffer.\n\n## Modding, v0.1 shape\n\nThe `strike` surface currently speaks: state snapshots (`hp`, `ammo`,\n`phase`, `aliveBots`, …), events (`hit`, `playerDamaged`, `playerDied`,\n`roundReset`), and commands (`setPhase`, `resetRound`, `addWin`\u002F`addLoss`,\n`setBotCount`, `configureWeapon`, `configureBots`). The HUD has the whole\nPocketJS `ui` surface. Both mount into one realm — a mod can restyle the\nHUD and rewrite the rules in the same file.\n\nOut of scope for v0.1: multiple weapons, buy phases, waypointed bot\nnavigation, networking, and a stable mod-distribution format. The surface\ngrows by appending, never by renumbering.\n\n## Assets\n\n- Bot character: see [assets\u002Fmodels\u002FCREDITS.md](assets\u002Fmodels\u002FCREDITS.md).\n- Map\u002Ftexture data (`.bsp`\u002F`.wad`) is © Valve and must be provided from your\n  own copy of the game.\n","OpenStrike 是一款类《反恐精英》的单人第一人称射击游戏，运行于跨平台 Pocket 运行时家族之上。其核心采用无标准库 Rust 编写（openstrike-core），确保桌面（wgpu）与复古硬件（如 2004 年索尼 PSP）共用同一份逻辑；游戏规则、HUD 和行为由嵌入式 QuickJS 执行 TypeScript\u002FJSX 代码实现，支持热更新与模块化开发。HUD 基于 Solid JSX 构建，通过 PocketJS 统一抽象渲染表面。项目适用于轻量级 FPS 原型验证、嵌入式游戏开发教学、跨平台运行时架构研究及复古硬件游戏移植。","2026-07-11 02:30:54","CREATED_QUERY"]