23 KiB
23 KiB
Project: Diablo II: Lord of Destruction (v1.13c) Pure-Browser Online Client (diablo2-web feat/netproto)
Architecture
- Pluggable, Zero-Dependency Network & Protocol Layer (
src/netproto/):- Strictly isolated from DOM, Node.js, rendering, and game simulation (
tsconfig.netproto.jsonsetslib: ["ES2022"], types: []for coresrc/netproto/**, excluding onlytransport/ws-stream.tsandtransport/node-tcp-stream.ts). - L0 Transport (
src/netproto/transport/):ByteStreaminterface implemented byMemoryStream(testing/offline replay),WsStream(browser WebSocket), andNodeTcpStream(Node CLI bot), plusEndpointResolver(wsBridgeResolvermapping6112 -> /d2net/bnet,6113 -> /d2net/realm,4000 -> /d2net/game;tcpResolver; andmixedResolverusing direct TCP101.37.117.183:6112for BNCS and WSS for MCP/D2GS so Node bots do not consume the 5-per-IP127.0.0.1WSS bridge quota). - L1–L3 Protocol Engines (
src/netproto/{core,crypto,bncs,mcp,d2gs}/):crypto/: Battle.net broken SHA-1 (xsha1), doubleHash, 1.13c CheckRevision constants (exeVersion=0x01000d00,exeHash=0x7686beca,exeInfo="Game.exe 03/09/10 04:10:51 61440"), and 16-char D2DV/D2XP CD-Key decode & hash.bncs/:0x01greeting +0xFF | id | u16 lenframing, OLS auth (0x50,0x25,0x51,0x3D,0x3A), chat (0x0A..0x0F), and realm handoff (0x40,0x3E).mcp/:0x01greeting +u16 len | u8 idframing (D2MCPClient.dll),0x01STARTUP,0x19CHARLIST2 (with 33-bytecharStatStringparser),0x02CHARCREATE,0x0ACHARDELETE,0x18CHARUPGRADE,0x07CHARLOGON,0x03CREATEGAME,0x04JOINGAME,0x05GAMELIST,0x06GAMEINFO,0x12MOTD.d2gs/: Generated 1.13c S→C packet size table (D2Net.dll0x6fbfa900181 entries + 14 variable-length formulas at0x6fbf6750and C→S0x6fbfabd8113 entries) and canonical Huffman bit-length table (Fog.dll0x6ff7f210+Fog.10219/Fog.10224MSB-first decompressor); initial uncompressed[0xAF, 0x01]greeting followed by 1/2-bytetotalFrameSizecompressed blocks (compressedPayloadLen = totalFrameSize - headerSize); fail-fastProtocolErroron unknown packet IDs or size mismatches; complete S→C (0x00..0xB4) and C→S (0x01..0x70) codecs,0x9C/0x9DLSB-first item bitstream decoder (ItemDataTablesinjection), andD2gsSession(0x6837-byte GameLogon,0x6BEnterGame, 5s 13-byte0x6DPing).
- L4 Neutral Domain & Flow (
src/netproto/domain/,src/netproto/flow/,src/netproto/index.ts):src/netproto/index.tsexports ONLY protocol-neutral domain types (ServerEvent,ClientCommand,GameServerAdapter,D2OnlineFlow,EndpointResolver,TextCodec,PacketTap, lobby models). External code (src/client/**,src/ui/**,src/scene/**,src/render/**,src/frontend/**) never importssrc/netproto/{bncs,mcp,d2gs,crypto}/**.
- Strictly isolated from DOM, Node.js, rendering, and game simulation (
- Runtime Seed-Driven DRLG & Tile Atlas Pipeline (
scripts/pack-tiles.ts,src/game/drlg/,src/client/map/):scripts/pack-tiles.tspacks allLvlTypes.txtDT1s across Acts 1–5 plus the 3 mandatory universal DT1s (Blank.dt1,InvisWal.dt1withstyle=49 sequence=7collision floor,Warp.dt1) and compact DRLG.bin/.ds1/DT1-header metadata intopublic/act-packs/tiles/.map-worker.ts&map-service.tsruncreateDrlgActSessionon(act, mapSeed, difficulty, areaId)fromLoadActandRoomRevealto produce exact pinned tile references, 16-bit sub-tile collision grids (COLLIDE_MASK_INVALIDon void cells), warps, waypoints, and preset units matching D2GS cell-for-cell.
- Packet-Driven Browser Client, Dual Viewport, Toolbar, Lobby, Audio & Inspector (
play.html,src/client/,src/ui/,src/frontend/):ClientWorldmaintains the authoritative server mirror (units,modes,directions,stats,states,skills,inventory/equipment/belt/stash/cube/cursor/trade/merc).ViewportProfilesupports800×600(1.13c native) and1024×768(HUD anchored at native pixel dimensions with(barOffsetX=112, barOffsetY=168), accurate screen-to-world mouse picking).- Top DOM
Toolbar(src/client/toolbar/) &ClientSettings(localStorage['d2web.settings.v1']): connection status/RTT + 5-per-IP/TLS diagnostics, Server Host editor (rejecting bare IP overhttps:), live中/ENtoggle, lighting level selector (auto/1.13c,LIGHTING_PRESETS,fullbright), automap reveal (off/level/act), viewport toggle (800×600/1024×768), and Packet Inspector toggle.
Feature Inventory
Every feature from the Survey phase and ORIGINAL_REQUEST.md appears here with its assigned milestone. No feature is left unassigned.
| # | Feature | Description | Milestone | Source |
|---|---|---|---|---|
| F1 | Module Isolation & TypeScript Boundary Enforcement | tsconfig.netproto.json (lib: ["ES2022"], types: []), tests/netproto/boundary.test.ts, and src/netproto/index.ts exporting only protocol-neutral interfaces (ServerEvent, ClientCommand, GameServerAdapter, D2OnlineFlow, EndpointResolver). |
M1 | R1, Survey 1 |
| F2 | Core Primitives, Framing, TextCodec & Transport Streams |
ByteReader, ByteWriter, BitReader, BitWriter, ProtocolError, TextCodec (defaulting to gbk via TextDecoder/TextEncoder), Clock, PacketTap, ByteStream, MemoryStream, WsStream, NodeTcpStream, EndpointResolver (wsBridgeResolver, tcpResolver, mixedResolver). |
M1 | R1, R6, Survey 1 & 3 |
| F3 | Deterministic 1.13c D2Net.dll / Fog.dll Table Extraction |
scripts/extract-d2net-tables.ts generating src/netproto/d2gs/tables/s2c-sizes.ts (0x6fbfa900 181 S→C sizes + 0x6fbf6750 14 variable-length formulas + 0x6fbfabd8 113 C→S sizes) and huffman.ts (Fog.dll 0x6ff7f210 256-byte bit-lengths + Fog.10219 canonical builder) with SHA-1s and offsets. |
M1 | R1, Survey 2 |
| F4 | Battle.net Crypto & BNCS Session State Machine | xsha1 broken SHA-1, doubleHash, CheckRevision 1.13c constants (0x01000d00, 0x7686beca, "Game.exe 03/09/10 04:10:51 61440"), 16-char D2DV/D2XP CD-Key decode & hash, BNCS `0xFF |
id | u16 len framing and packets (0x50, 0x25, 0x51, 0x3D, 0x3A, 0x0A..0x0F, 0x40, 0x3E`). |
| F5 | MCP Realm Session & D2OnlineFlow Orchestration |
MCP 0x01 greeting + `u16 len |
u8 id framing (0x01STARTUP,0x19CHARLIST2 with 33B stat string,0x02CHARCREATE,0x0ACHARDELETE,0x18CHARUPGRADE,0x07CHARLOGON,0x03CREATEGAME,0x04JOINGAME,0x05GAMELIST,0x06GAMEINFO,0x12MOTD),D2OnlineFlow, and initial scripts/d2-bot.ts account registration (d2webbot1..3inscratch/bot-accounts.json`). |
M1 |
| F6 | D2GS Block Framing, Huffman Decompression & Session Handshake | Initial uncompressed [0xAF, 0x01] greeting, 1/2-byte totalFrameSize block header (compressedPayloadLen = totalFrameSize - headerSize), Fog.10224 MSB-first Huffman decompressor (+ encoder for tests), D2NET_10033 packet splitter with fail-fast ProtocolError, 37-byte 0x68 GameLogon, 0x6B EnterGame, and 5s 13-byte 0x6D Ping loop. |
M2 | R1, R2, Survey 2 |
| F7 | Complete D2GS S→C (0x00..0xB4) & C→S (0x01..0x70) Codecs & D2gsAdapter |
Full table-driven S→C and C→S packet definitions (load, units, movement, stats, skills, states, items, npc, quest, waypoint, party, trade, chat, merc, misc), registry.ts with D2Client.dll 0x6fb8de60 handler VAs, and D2gsAdapter implements GameServerAdapter. |
M2 | R1, R2, Survey 2 |
| F8 | 1.13c 0x9C / 0x9D Item Bitstream Decoder |
src/netproto/d2gs/items/item-bitstream.ts with injected ItemDataTables (ItemStatCost, Armor, Weapons, Misc), decoding 8B 0x9C and 13B 0x9D headers, ground 16+16b coords vs container 4+4+3b coords, "gld " gold piles, compact vs extended items, sockets, runewords, and 0x1FF-terminated stat lists. |
M2 | R1, R2, Survey 2 |
| F9 | Headless ClientWorld Authoritative Mirror |
src/client/world/{client-world,client-unit,stat-list,states,inventory,self,item-tables-provider}.ts maintaining units, modes, directions, stats, states, skills, and all item containers (inventory, equipment, belt, stash, cube, cursor, trade, merc, shop, ground) from ServerEvents. |
M2 | R2, R4, Survey 1 & 2 |
| F10 | Live .d2cap Capture Corpus & Strict Offline Replay (scripts/netproto-replay.ts) |
Complete scripts/d2-bot.ts (register, login, chars, create-char, games, create-game, join, idle, record, --world) + scripts/netproto-replay.ts --strict verifying tests/fixtures/netproto/*.d2cap with unknownPackets === 0, opaquePackets === 0, protocolErrors === 0, and >=60s live D2GS stability. |
M2 | R2, Survey 2 & 3 |
| F11 | Seed-Independent Tile Library Asset Pack (scripts/pack-tiles.ts) |
Offline packer generating per-act DT1 tile atlases and compact DRLG .bin/.ds1/DT1-header bundles covering all LvlTypes.txt DT1s across Acts 1–5 plus the 3 mandatory universal DT1s (Blank.dt1, InvisWal.dt1 with style=49 sequence=7, Warp.dt1). |
M3 | R3, Survey 1 & 3 |
| F12 | Runtime DRLG Web Worker, LevelView, TileAtlas & Motion/Pathfinding |
createDrlgActSession (drlg-dump.ts, drlg-map.ts), src/client/map/{level-view,tile-atlas,map-worker,map-service}.ts, and src/client/motion/{pathfind,predictor,interpolate}.ts generating exact pinned tile references, COLLIDE_MASK_INVALID void cell blocking, warps, and preset units on LoadAct / RoomReveal. |
M3 | R3, Survey 1 & 3 |
| F13 | Offline .d2s Waypoint/Quest Unlock (scripts/d2s-unlock.ts) & 136-Level Parity Audit |
scripts/d2s-unlock.ts (backing up offline d2webbot* save on 101.37.117.183 /usr/local/var/pvpgn/charsave/ before unlocking all 39 waypoints & act-transition quests and recomputing checksum) + bot continuous walk test (0 UnitReassign pullbacks) + automated level audit verifying 100% coordinate parity across all reachable levels and all 136 level IDs. |
M3 | R3, R6, Survey 1 & 3 |
| F14 | Persistent ClientSettings & Top DOM Toolbar (src/client/toolbar/) |
src/client/settings/{client-settings,settings-store}.ts (localStorage['d2web.settings.v1'] strict validation) and src/client/toolbar/{toolbar.ts,toolbar.css}: connection status/RTT + 5-per-IP & TLS diagnostics + Packet Inspector toggle, Server Host editor (rejecting bare IP over https: with explicit error, prompting mid-game), live 中/EN toggle, lighting selector, automap reveal (off/level/act), and viewport toggle (800×600/1024×768). |
M4 | R5, Survey 1 & 3 |
| F15 | Dual Viewport Profiles (800×600 & 1024×768), SceneSource & LightingInputs |
src/client/view/{viewport-profile,scene-source,unit-drawables}.ts and non-breaking refactoring of src/scene/frontend/{lighting-presets,world-renderer,pack-loader,mouse-controller}.ts (adding fullbright preset and keeping acts.html 100% working). |
M4 | R4, R5, Survey 1 |
| F16 | play.html Entry, Client Movement Prediction, Combat, Skills & Native Missile/Overlay FX |
play.html, src/client/{main,session/online-session,input/command-mapper}.ts rendering terrain, units, client-predicted movement with smooth UnitReassign reconciliation, left/right-hand skill casting, and native DCC/DC6 missile & overlay FX (Missiles.txt, additive blending Trans: 1 with zero black fringes). |
M4 | R4, Survey 1 & 3 |
| F17 | Full HUD/Panel Rebinding (HudModel), 1024×768 Layout & Automap Reveal Modes |
src/client/ui-model/hud-model.ts, src/client/automap/automap-view.ts, and src/ui/** updates (anchoring panels at native pixel dimensions in 800×600 and 1024×768 without stretching art; wiring inventory, equipment, belt, stash, Horadric Cube, char sheet, skill tree, quest log, waypoint menu, NPC dialog/shop/repair/gamble/imbue, merc, party, trade, chat, Esc menu, death overlay, 1.13c hotkeys, and off/level/act automap reveal). |
M5 | R4, R5, Survey 1 |
| F18 | Live Battle.net Lobby Flow (bnet.html & play.html via D2OnlineFlow) |
Connect src/frontend/{flow-state,bnet-main}.ts and play.html / bnet.html to real D2OnlineFlow sessions for login/register, channel chat, realm selection, char list/create/delete/convert, and game list/create/join, replacing mocks and transitioning into the in-game view. |
M5 | R4, Survey 1 & 3 |
| F19 | Web Audio Engine (Sounds.txt, SoundEnviron.txt, HTTP Range & OPFS MPQ Caching) |
src/client/audio/sound-service.ts and src/client/assets/opfs-mpq.ts wiring server PlaySound events, skill/combat/UI actions, footsteps, per-level background music, and NPC speech audio to src/audio/manager.ts via HTTP 206 Range MPQ streaming (/diablo2/data/*.mpq) and optional browser OPFS MPQ caching. |
M5 | R4, Survey 1, 2 & 3 |
| F20 | Hardening, Rate Limiting, Packet Inspector & .d2cap Replay Panel, and scripts/verify-play.ts |
Graceful disconnect handling to lobby with reason, C→S outbound packet rate limiter, in-browser Packet Inspector & .d2cap Replay Panel (src/client/inspector/packet-inspector.ts), and headless Chrome CDP verification script scripts/verify-play.ts testing the complete lobby, gameplay, audio, dual viewport, and Toolbar matrix. |
M5 | R4, R5, Survey 1 & 3 |
Milestones
| # | Name | Scope | Dependencies | Status |
|---|---|---|---|---|
| M1 | M1-Netproto-Core-BNCS-MCP-Bot |
Phases N0–N1: tsconfig.netproto.json, scripts/extract-d2net-tables.ts (s2c-sizes.ts, huffman.ts), src/netproto/{core,transport,crypto,bncs,mcp,domain,flow,ts,index.ts}, tests/netproto/boundary.test.ts, unit tests, and initial scripts/d2-bot.ts (register, login, chars, create-char, games, create-game, join via mixed and wss resolvers, registering d2webbot1..3). |
none | DONE (worker_m1_m2_1 3d592731-8e41-4232-8b8a-3c8ce484ed25) |
| M2 | M2-D2GS-Protocol-Items-ClientWorld-Replay |
Phases N2–N3: src/netproto/d2gs/{compression,framing-s2c,framing-c2s,s2c/*,c2s/*,items/*,registry,session,adapter}.ts, headless src/client/world/**, scripts/d2-bot.ts (idle, record, --world >=60s live session), tests/fixtures/netproto/*.d2cap, and scripts/netproto-replay.ts --strict (0 unknown/opaque/error packets). |
M1 | DONE (worker_m1_m2_1 3d592731-8e41-4232-8b8a-3c8ce484ed25, 949 records replayed with 0 unknown/opaque/errors) |
| M3 | M3-Runtime-DRLG-TileAtlas-And-136Level-Parity |
Phase N4: createDrlgActSession (src/game/drlg/{drlg-dump,drlg-map}.ts), scripts/pack-tiles.ts (all LvlTypes.txt DT1s + 3 universal DT1s), src/client/map/{level-view,tile-atlas,map-worker,map-service}.ts, src/client/motion/{pathfind,predictor,interpolate}.ts, scripts/d2s-unlock.ts, and bot walk (0 UnitReassign) + 136-level coordinate parity audit. |
M1, M2 | DONE (core DRLG/TileAtlas/motion/d2s-unlock/136-level parity by worker_m3_1 7ce7de0c-9422-4066-963f-d8a4fbbf4604; live bot walk/level audit in M5) |
| M4 | M4-Browser-Client-Viewport-Toolbar-Combat-Lighting |
Phases N5–N6 + D1 & D5: src/client/settings/**, src/client/toolbar/**, src/client/view/{viewport-profile,scene-source,unit-drawables}.ts, src/scene/frontend/{lighting-presets,world-renderer,pack-loader,mouse-controller}.ts decoupling, src/client/{automap,audio,assets,inspector,session/rate-limiter}/**, src/i18n/lang.ts, and src/ui/** 1024×768 anchoring. |
M1, M2, M3 | DONE (worker_m4_1 f4b38de0-c797-4090-adef-79975dd9303b, 61/61 tests passing) |
| M5 | M5-UI-Panels-Automap-Lobby-Audio-Inspector |
Phases N7–N10: src/client/ui-model/hud-model.ts, src/client/input/command-mapper.ts, src/client/session/online-session.ts, src/client/main.ts, play.html, src/frontend/** live D2OnlineFlow lobby integration, scripts/d2-bot.ts live walk & level audit, and scripts/verify-play.ts. |
M4 | DONE (worker_m5_1 9abb87be-ab83-4c74-a11a-6e7744dc79db, walk/audit-levels/verify-play 9/9 passed) |
| E2E | E2E-Testing-Track |
Opaque-box requirement-driven E2E test infrastructure (TEST_INFRA.md) and 4-tier test suite (tests/e2e-netproto/tier1..4.test.ts covering all 20 features F1–F20 with >=100 Tier 1, >=100 Tier 2, >=20 Tier 3, >=10 Tier 4 test cases), publishing TEST_READY.md. |
M1–M5 | DONE (test_writer_e2e_1 03a98a04-9653-4c1d-84e3-681be87b6f29, 236/236 E2E tests passing) |
| M6 | M6-Final-E2E-Pass-And-Tier5-Hardening |
Phase 1: Pass 100% of E2E tests (Tiers 1–4) and all Acceptance Criteria (tsc, vitest, npm run build, boundary.test.ts, extract-d2net-tables.ts, d2-bot.ts, netproto-replay.ts --strict, verify-play.ts). Phase 2: Tier 5 white-box adversarial coverage hardening (tests/e2e-netproto/tier5-adversarial-coverage.test.ts 32/32 passed, 268/268 Tiers 1–5 passed) + clean git worktree check. |
M1–M5, E2E | DONE (reviewer_m6_1 APPROVE, reviewer_m6_2 APPROVE, challenger_m6_1_gen2 APPROVE, challenger_m6_2 APPROVE, auditor_m6_1 CLEAN) |
| M7 | M7-Round2-Victory-Audit-Remediation |
Remediate all 4 Round 1 Victory Auditor violations (B1: live FrontendAsyncHandlers lobby in play.html & bnet.html, deleting enterInGameDemo; B2: WebGL2 SpriteRenderer + TileAtlasGpuCache + LightGrid + Minimap on #view, deleting renderWorldAndAutomapOn2dCanvas; B3: canonical 167-opcode decodeD2gsS2cPacket + D2gsS2cFramer in OnlineSession with 0 UnknownS2c across all 4 .d2cap files + 9-Gate live scripts/verify-play.ts; B4: SSH ControlMaster .d2s unlock + live 5-Act 20-waypoint scripts/d2-bot.ts audit-levels tour across Acts 1–5 + map-service.ts Vite fix). |
M1–M6 | DONE (worker_r2_1, worker_r2_2, worker_r2_3 DONE; reviewer_r2_1_gen2 APPROVE, reviewer_r2_2 APPROVE, challenger_r2_1_gen2 APPROVE, challenger_r2_2 APPROVE, auditor_r2_1 CLEAN, auditor_r2_2 CLEAN) |
Interface Contracts
1. src/netproto/index.ts ↔ src/client/** & src/frontend/**
src/netproto/index.tsis the ONLY allowed entry point intosrc/netproto/from outsidesrc/netproto/(exceptsrc/netproto/transport/*where needed by Node scripts).- Exports:
ByteStream,CloseReason,EndpointKind,EndpointResolver,createWsBridgeResolver,createTcpResolver,createMixedResolver,createMemoryStreamPairTextCodec,createBrowserTextCodec,PacketTap,PacketTapEntry,ProtocolError,ClosedError,TimeoutError,Clock,systemClockUnitType,UnitRef,Pt,Hand,ItemContainer,ItemData,ItemStat,ItemDataTables,UnitSnapshot,SkillLevel,CharSummary,GameSummary,RealmInfo,ChatEventServerEvent(discriminated union:GameLoading,GameFlags,LoadAct,LoadComplete,UnloadComplete,GameLogout,RoomReveal,RoomHide,UnitAssign,UnitRemove,UnitMove,UnitReassign,UnitMode,SkillCast,StatSet,LifeMana,Experience,StateSet,StateEnd,ItemEvent,SkillList,ActiveSkill,Npc,WaypointMenu,QuestState,Party,Trade,Chat,PlaySound,Merc,Portal,Pong,Warden,SaveChunk,Opaque)ClientCommand(discriminated union:Move,MoveToUnit,SkillAt,SkillOn,SelectSkill,Interact,TakeWarp,ItemPickup,ItemDrop,ItemToCursor,ItemPlace,ItemEquip,ItemUnequip,ItemSwap,BeltPut,BeltRemove,BeltUse,ItemUse,SocketItem,IdentifyItem,NpcInit,NpcCancel,NpcBuy,NpcSell,NpcRepair,NpcHeal,NpcGamble,NpcIdentifyAll,NpcResurrectMerc,HireMerc,AddStatPoint,AddSkillPoint,WaypointGo,TownPortal,ClickButton,Party,Hostile,Trade,Chat,OverheadChat,Resurrect,SwapWeapons,Ping,LeaveGame)GameServerAdapter(state,send,onEvent,onClose,leave,stats)OnlineConfig,D2OnlineFlow(connect,createAccount,login,enterChat,joinChannel,sendChat,onChatEvent,listRealms,realmLogon,listChars,createChar,deleteChar,upgradeChar,charLogon,listGames,getGameInfo,createGame,joinGame,close)
2. src/client/world/client-world.ts ↔ src/client/{map,motion,view,ui-model}/**
ClientWorldconsumesServerEventviaapply(ev: ServerEvent): voidand exposes read-only snapshots of:act,mapSeed,difficulty,hardcore,expansion,ladder,areaId,loading,selfIdself: SelfPlayerState(unitId,name,charClass,level,x,y,life,maxLife,mana,maxMana,stamina,maxStamina,gold,stashGold,experience,stats,skills,leftSkill,rightSkill,runMode,weaponSet,mercId)units: ReadonlyMap<string, ClientUnit>(keyed by${unitType}:${id})containers: ClientItemContainers(inventory,equipment,belt,stash,cube,cursor,tradeSelf,tradePartner,merc,shop,ground)revealedRooms: ReadonlySet<string>(${areaId}:${tileX}:${tileY})waypoints: ReadonlySet<number>,quests: ReadonlyUint16Array,party,trade,chatLog,soundQueue
3. src/client/map/map-service.ts ↔ src/game/drlg/** & src/client/view/scene-source.ts
MapService.loadAct(act: number, mapSeed: number, difficulty: number, initialAreaId: number): Promise<LevelView>MapService.revealRoom(areaId: number, roomTileX: number, roomTileY: number): Promise<LevelView>LevelView:{ act, mapSeed, difficulty, areaId, originX, originY, width, height, collision: Uint16Array, blocked: Uint8Array, floors, shadows, walls, roofs, warps, presetUnits, automap, rooms }
4. src/client/settings/client-settings.ts & ViewportProfile ↔ Toolbar, WorldRenderer, HudManager
ClientSettingsstored underlocalStorage['d2web.settings.v1']with strict schema validation.ViewportProfile:{ id: '800x600' | '1024x768', width: 800 | 1024, height: 600 | 768, barOffsetX: 0 | 112, barOffsetY: 0 | 168, panelOffsetY: 0 | 84 }.LightingInputsdecouplessrc/scene/frontend/lighting-presets.tsfromGameEngine.SceneSourcedecouplessrc/scene/frontend/world-renderer.tsfromGameEngine.
Code Layout
src/netproto/: Isolated, zero-dependency network & protocol package (core/,transport/,crypto/,bncs/,mcp/,d2gs/,domain/,flow/,ts/,index.ts).src/client/: Packet-driven online client (world/,map/,motion/,input/,view/,ui-model/,settings/,toolbar/,automap/,audio/,assets/,inspector/,session/,main.ts).play.html: Online client HTML entry point with top DOM Toolbar and dual-viewport WebGL2 + 2D HUD canvas stage.scripts/extract-d2net-tables.ts: Deterministic 1.13cD2Net.dll&Fog.dlltable generator.scripts/d2-bot.ts: Headless Node CLI bot (register,login,chars,create-char,games,create-game,join,idle,record,walk,audit-levels).scripts/netproto-replay.ts: Offline.d2capJSONL capture replay & strict coverage verifier.scripts/pack-tiles.ts: Seed-independent DT1 tile library & DRLG metadata packer.scripts/d2s-unlock.ts: Safe offlined2webbot*.d2swaypoint & act-progression unlocker with timestamped backup.scripts/verify-play.ts: Headless Chrome CDP E2E verifier forplay.htmlacross800×600&1024×768viewports and all Toolbar controls.tests/netproto/,tests/client/,tests/e2e-netproto/: Unit, boundary, golden replay, and 5-tier E2E test suites.