1 line
17 KiB
JSON
1 line
17 KiB
JSON
[{"data":1,"prerenderedAt":688},["ShallowReactive",2],{"navigation_docs":3,"-getting-started-development":145,"-getting-started-development-surround":683},[4,27,41,93],{"title":5,"path":6,"stem":7,"children":8,"icon":26},"Getting Started","\u002Fgetting-started","1.getting-started\u002F0.index",[9,10,14,18,22],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Framework Architecture","\u002Fgetting-started\u002Farchitecture","1.getting-started\u002F1.architecture",{"title":15,"path":16,"stem":17},"Module Reference","\u002Fgetting-started\u002Fmodule-reference","1.getting-started\u002F2.module-reference",{"title":19,"path":20,"stem":21},"Development Guide","\u002Fgetting-started\u002Fdevelopment","1.getting-started\u002F3.development",{"title":23,"path":24,"stem":25},"SurrealDB Setup","\u002Fgetting-started\u002Fsurrealdb-setup","1.getting-started\u002F4.surrealdb-setup","i-lucide-rocket",{"title":28,"path":29,"stem":30,"children":31},"Forge Server Extension","\u002Fserver-extension","2.server-extension\u002F0.index",[32,33,37],{"title":28,"path":29,"stem":30},{"title":34,"path":35,"stem":36},"Forge Server API Reference","\u002Fserver-extension\u002Fapi-reference","2.server-extension\u002F1.api-reference",{"title":38,"path":39,"stem":40},"Forge Server Usage Examples","\u002Fserver-extension\u002Fusage-examples","2.server-extension\u002F2.usage-examples",{"title":42,"path":43,"stem":44,"children":45,"icon":92},"Server Modules","\u002Fserver-modules","3.server-modules\u002F0.index",[46,48,52,56,60,64,68,72,76,80,84,88],{"title":47,"path":43,"stem":44},"Server Module Guides",{"title":49,"path":50,"stem":51},"Actor Usage Guide","\u002Fserver-modules\u002Factor","3.server-modules\u002F1.actor",{"title":53,"path":54,"stem":55},"Store Usage Guide","\u002Fserver-modules\u002Fstore","3.server-modules\u002F10.store",{"title":57,"path":58,"stem":59},"Task Usage Guide","\u002Fserver-modules\u002Ftask","3.server-modules\u002F11.task",{"title":61,"path":62,"stem":63},"Bank Usage Guide","\u002Fserver-modules\u002Fbank","3.server-modules\u002F2.bank",{"title":65,"path":66,"stem":67},"CAD Usage Guide","\u002Fserver-modules\u002Fcad","3.server-modules\u002F3.cad",{"title":69,"path":70,"stem":71},"Economy Usage Guide","\u002Fserver-modules\u002Feconomy","3.server-modules\u002F4.economy",{"title":73,"path":74,"stem":75},"Garage Usage Guide","\u002Fserver-modules\u002Fgarage","3.server-modules\u002F5.garage",{"title":77,"path":78,"stem":79},"Locker Usage Guide","\u002Fserver-modules\u002Flocker","3.server-modules\u002F6.locker",{"title":81,"path":82,"stem":83},"Organization Usage Guide","\u002Fserver-modules\u002Forganization","3.server-modules\u002F7.organization",{"title":85,"path":86,"stem":87},"Owned Storage Usage Guide","\u002Fserver-modules\u002Fowned-storage","3.server-modules\u002F8.owned-storage",{"title":89,"path":90,"stem":91},"Phone Usage Guide","\u002Fserver-modules\u002Fphone","3.server-modules\u002F9.phone","i-lucide-layers-3",{"title":94,"path":95,"stem":96,"children":97,"icon":144},"Client Addons","\u002Fclient-addons","4.client-addons\u002F0.index",[98,100,104,108,112,116,120,124,128,132,136,140],{"title":99,"path":95,"stem":96},"Client Usage Guide",{"title":101,"path":102,"stem":103},"Client Main Usage Guide","\u002Fclient-addons\u002Fmain","4.client-addons\u002F1.main",{"title":105,"path":106,"stem":107},"Client Phone Usage Guide","\u002Fclient-addons\u002Fphone","4.client-addons\u002F10.phone",{"title":109,"path":110,"stem":111},"Client Store Usage Guide","\u002Fclient-addons\u002Fstore","4.client-addons\u002F11.store",{"title":113,"path":114,"stem":115},"Client Common Usage Guide","\u002Fclient-addons\u002Fcommon","4.client-addons\u002F2.common",{"title":117,"path":118,"stem":119},"Client Actor Usage Guide","\u002Fclient-addons\u002Factor","4.client-addons\u002F3.actor",{"title":121,"path":122,"stem":123},"Client Bank Usage Guide","\u002Fclient-addons\u002Fbank","4.client-addons\u002F4.bank",{"title":125,"path":126,"stem":127},"Client CAD Usage Guide","\u002Fclient-addons\u002Fcad","4.client-addons\u002F5.cad",{"title":129,"path":130,"stem":131},"Client Garage Usage Guide","\u002Fclient-addons\u002Fgarage","4.client-addons\u002F6.garage",{"title":133,"path":134,"stem":135},"Client Locker Usage Guide","\u002Fclient-addons\u002Flocker","4.client-addons\u002F7.locker",{"title":137,"path":138,"stem":139},"Client Notifications Usage Guide","\u002Fclient-addons\u002Fnotifications","4.client-addons\u002F8.notifications",{"title":141,"path":142,"stem":143},"Client Organization Usage Guide","\u002Fclient-addons\u002Forganization","4.client-addons\u002F9.organization","i-lucide-monitor-smartphone",{"id":146,"title":19,"body":147,"description":157,"extension":678,"links":679,"meta":680,"navigation":517,"path":20,"seo":681,"stem":21,"__hash__":682},"docs\u002F1.getting-started\u002F3.development.md",{"type":148,"value":149,"toc":668},"minimark",[150,154,158,163,170,173,215,218,227,230,239,243,246,350,354,451,455,458,486,493,496,546,550,553,556,574,578,581,613,619,623,630,637,641,644,664],[151,152,19],"h1",{"id":153},"development-guide",[155,156,157],"p",{},"This guide covers the usual path for adding or changing a Forge module.",[159,160,162],"h2",{"id":161},"local-checks","Local Checks",[155,164,165,166,169],{},"Before running storage-backed workflows locally, complete\n",[167,168,23],"a",{"href":24},".",[155,171,172],{},"Run these before pushing Rust or extension changes:",[174,175,180],"pre",{"className":176,"code":177,"language":178,"meta":179,"style":179},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cargo fmt --check\ncargo check\ncargo test\ncargo build\ncargo clippy --all-targets --all-features -- -D warnings\n","powershell","",[181,182,183,191,197,203,209],"code",{"__ignoreMap":179},[184,185,188],"span",{"class":186,"line":187},"line",1,[184,189,190],{},"cargo fmt --check\n",[184,192,194],{"class":186,"line":193},2,[184,195,196],{},"cargo check\n",[184,198,200],{"class":186,"line":199},3,[184,201,202],{},"cargo test\n",[184,204,206],{"class":186,"line":205},4,[184,207,208],{},"cargo build\n",[184,210,212],{"class":186,"line":211},5,[184,213,214],{},"cargo clippy --all-targets --all-features -- -D warnings\n",[155,216,217],{},"Run this after changing browser UI sources:",[174,219,221],{"className":176,"code":220,"language":178,"meta":179,"style":179},"npm run build:webui\n",[181,222,223],{"__ignoreMap":179},[184,224,225],{"class":186,"line":187},[184,226,220],{},[155,228,229],{},"Build Arma packages with:",[174,231,233],{"className":176,"code":232,"language":178,"meta":179,"style":179},".\\build-arma.ps1\n",[181,234,235],{"__ignoreMap":179},[184,236,237],{"class":186,"line":187},[184,238,232],{},[159,240,242],{"id":241},"module-boundaries","Module Boundaries",[155,244,245],{},"Keep each layer responsible for one kind of work:",[247,248,249,265],"table",{},[250,251,252],"thead",{},[253,254,255,259,262],"tr",{},[256,257,258],"th",{},"Layer",[256,260,261],{},"Owns",[256,263,264],{},"Avoid",[266,267,268,282,295,308,321,337],"tbody",{},[253,269,270,276,279],{},[271,272,273],"td",{},[181,274,275],{},"lib\u002Fmodels",[271,277,278],{},"Data structures, serde defaults, validation helpers.",[271,280,281],{},"Database calls, SQF-specific context.",[253,283,284,289,292],{},[271,285,286],{},[181,287,288],{},"lib\u002Frepositories",[271,290,291],{},"Repository traits and in-memory stores.",[271,293,294],{},"SurrealDB-specific code.",[253,296,297,302,305],{},[271,298,299],{},[181,300,301],{},"lib\u002Fservices",[271,303,304],{},"Business rules, workflow orchestration, structured results.",[271,306,307],{},"Arma engine calls, extension transport details.",[253,309,310,315,318],{},[271,311,312],{},[181,313,314],{},"arma\u002Fserver\u002Fextension",[271,316,317],{},"Command parsing, context resolution, SurrealDB implementations, serialization to SQF.",[271,319,320],{},"Business rules that belong in services.",[253,322,323,328,334],{},[271,324,325],{},[181,326,327],{},"arma\u002Fserver\u002Faddons",[271,329,330,331,169],{},"Server SQF lifecycle, game-object integration, calls into ",[181,332,333],{},"forge_server",[271,335,336],{},"Direct database logic.",[253,338,339,344,347],{},[271,340,341],{},[181,342,343],{},"arma\u002Fclient\u002Faddons",[271,345,346],{},"Client UI, keybinds, local UI events.",[271,348,349],{},"Authoritative persistence.",[159,351,353],{"id":352},"adding-a-domain-module","Adding a Domain Module",[355,356,357,364,370,376,379,385,391,394,400,406,412,418,424,430,437,444],"ol",{},[358,359,360,361,169],"li",{},"Add the model in ",[181,362,363],{},"lib\u002Fmodels\u002Fsrc\u002F\u003Cmodule>.rs",[358,365,366,367,169],{},"Export the model from ",[181,368,369],{},"lib\u002Fmodels\u002Fsrc\u002Flib.rs",[358,371,372,373,169],{},"Add repository traits in ",[181,374,375],{},"lib\u002Frepositories\u002Fsrc\u002F\u003Cmodule>.rs",[358,377,378],{},"Add in-memory repository support if the service needs tests or hot state.",[358,380,381,382,169],{},"Export the traits from ",[181,383,384],{},"lib\u002Frepositories\u002Fsrc\u002Flib.rs",[358,386,387,388,169],{},"Add service logic in ",[181,389,390],{},"lib\u002Fservices\u002Fsrc\u002F\u003Cmodule>.rs",[358,392,393],{},"Add focused unit tests for service behavior.",[358,395,396,397,169],{},"Export the service from ",[181,398,399],{},"lib\u002Fservices\u002Fsrc\u002Flib.rs",[358,401,402,403,169],{},"Add a SurrealDB schema module under ",[181,404,405],{},"arma\u002Fserver\u002Fextension\u002Fsrc\u002Fschema",[358,407,408,409,169],{},"Add the concrete storage adapter under ",[181,410,411],{},"arma\u002Fserver\u002Fextension\u002Fsrc\u002Fstorage",[358,413,414,415,169],{},"Register the storage adapter in ",[181,416,417],{},"arma\u002Fserver\u002Fextension\u002Fsrc\u002Fstorage.rs",[358,419,420,421,169],{},"Add an extension command group under ",[181,422,423],{},"arma\u002Fserver\u002Fextension\u002Fsrc\u002F\u003Cmodule>.rs",[358,425,426,427,169],{},"Register the command group in ",[181,428,429],{},"arma\u002Fserver\u002Fextension\u002Fsrc\u002Flib.rs",[358,431,432,433,436],{},"Add server addon functions under ",[181,434,435],{},"arma\u002Fserver\u002Faddons\u002F\u003Cmodule>"," if SQF needs a module-level API.",[358,438,439,440,443],{},"Add client addon or browser UI files under ",[181,441,442],{},"arma\u002Fclient\u002Faddons\u002F\u003Cmodule>"," if the module has player-facing UI.",[358,445,446,447,450],{},"Add documentation in ",[181,448,449],{},"docs\u002F"," and module-level READMEs.",[159,452,454],{"id":453},"extension-command-rules","Extension Command Rules",[155,456,457],{},"Commands should return one of these forms:",[459,460,461,464,474,480],"ul",{},[358,462,463],{},"JSON string for structured results.",[358,465,466,469,470,473],{},[181,467,468],{},"\"true\""," or ",[181,471,472],{},"\"false\""," for simple existence and boolean operations.",[358,475,476,479],{},[181,477,478],{},"\"OK\""," for successful destructive operations with no response body.",[358,481,482,485],{},[181,483,484],{},"\"Error: \u003Cmessage>\""," for failures.",[155,487,488,489,492],{},"Prefer stable JSON shapes over ad hoc strings. SQF callers should always check\nfor the ",[181,490,491],{},"\"Error:\""," prefix before parsing JSON.",[155,494,495],{},"Example:",[174,497,501],{"className":498,"code":499,"language":500,"meta":179,"style":179},"language-sqf shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","private _result = \"forge_server\" callExtension [\"actor:get\", [getPlayerUID player]];\nprivate _payload = _result select 0;\n\nif (_payload find \"Error:\" == 0) exitWith {\n systemChat format [\"Actor request failed: %1\", _payload];\n};\n\nprivate _actor = fromJSON _payload;\n","sqf",[181,502,503,508,513,519,524,529,535,540],{"__ignoreMap":179},[184,504,505],{"class":186,"line":187},[184,506,507],{},"private _result = \"forge_server\" callExtension [\"actor:get\", [getPlayerUID player]];\n",[184,509,510],{"class":186,"line":193},[184,511,512],{},"private _payload = _result select 0;\n",[184,514,515],{"class":186,"line":199},[184,516,518],{"emptyLinePlaceholder":517},true,"\n",[184,520,521],{"class":186,"line":205},[184,522,523],{},"if (_payload find \"Error:\" == 0) exitWith {\n",[184,525,526],{"class":186,"line":211},[184,527,528],{}," systemChat format [\"Actor request failed: %1\", _payload];\n",[184,530,532],{"class":186,"line":531},6,[184,533,534],{},"};\n",[184,536,538],{"class":186,"line":537},7,[184,539,518],{"emptyLinePlaceholder":517},[184,541,543],{"class":186,"line":542},8,[184,544,545],{},"private _actor = fromJSON _payload;\n",[159,547,549],{"id":548},"persistence-rules","Persistence Rules",[155,551,552],{},"SurrealDB is the durable store. Keep database-specific mapping in the extension\nstorage adapters, not in services or repository traits.",[155,554,555],{},"When changing persisted data:",[459,557,558,565,568,571],{},[358,559,560,561,564],{},"Update or add the matching ",[181,562,563],{},".surql"," schema module.",[358,566,567],{},"Update the concrete storage adapter.",[358,569,570],{},"Preserve existing records when possible through serde defaults or migration\nlogic.",[358,572,573],{},"Add tests at the service level for behavior, and add storage tests only when\ndatabase mapping is the risk.",[159,575,577],{"id":576},"hot-state-rules","Hot-State Rules",[155,579,580],{},"Use hot state for data that is read or mutated frequently during a player\nsession. Hot-state modules usually provide:",[459,582,583,589,595,601,607],{},[358,584,585,588],{},[181,586,587],{},"init"," to load durable state into memory.",[358,590,591,594],{},[181,592,593],{},"get"," to read the runtime copy.",[358,596,597,600],{},[181,598,599],{},"override"," or focused mutation commands to update the runtime copy.",[358,602,603,606],{},[181,604,605],{},"save"," to write the runtime copy back to SurrealDB.",[358,608,609,612],{},[181,610,611],{},"remove"," to evict the runtime copy.",[155,614,615,616,618],{},"Do not assume hot state is durable until ",[181,617,605],{}," succeeds.",[159,620,622],{"id":621},"web-ui-rules","Web UI Rules",[155,624,625,626,629],{},"Browser UI source files live under each client addon. Built assets usually land\nunder that addon's ",[181,627,628],{},"ui\u002F_site"," directory.",[155,631,632,633,636],{},"Use the existing common bridge in ",[181,634,635],{},"arma\u002Fclient\u002Faddons\u002Fcommon"," when a UI needs\nto send events back to SQF. Keep UI state and rendering in JavaScript, and keep\nserver-authoritative decisions in server SQF or Rust services.",[159,638,640],{"id":639},"documentation-checklist","Documentation Checklist",[155,642,643],{},"When adding or changing a module, update:",[459,645,646,652,655,661],{},[358,647,648,651],{},[181,649,650],{},"docs\u002FMODULE_REFERENCE.md"," for framework-level inventory.",[358,653,654],{},"A module-specific README in the addon directory when SQF or UI usage changes.",[358,656,657,660],{},[181,658,659],{},"arma\u002Fserver\u002Fdocs\u002Fapi-reference.md"," when extension commands change.",[358,662,663],{},"Existing usage guides when payload shapes or workflows change.",[665,666,667],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":179,"searchDepth":193,"depth":193,"links":669},[670,671,672,673,674,675,676,677],{"id":161,"depth":193,"text":162},{"id":241,"depth":193,"text":242},{"id":352,"depth":193,"text":353},{"id":453,"depth":193,"text":454},{"id":548,"depth":193,"text":549},{"id":576,"depth":193,"text":577},{"id":621,"depth":193,"text":622},{"id":639,"depth":193,"text":640},"md",null,{},{"title":19,"description":157},"SACXFQxkQonJpusqYCXgr0NFhrv1Imz0UFQfb7-7iGg",[684,686],{"title":15,"path":16,"stem":17,"description":685,"children":-1},"This reference lists the main Forge modules and where each layer lives.",{"title":23,"path":24,"stem":25,"description":687,"children":-1},"Forge uses SurrealDB for durable storage. The Rust server extension connects to\nSurrealDB on startup and applies Forge schema modules automatically, so setup\ncomes down to running a reachable database and matching the Forge config.",1776806627742] |