[{"data":1,"prerenderedAt":1359},["ShallowReactive",2],{"doc:\u002Fgame-engine\u002Fdata\u002Fsaves":3,"surround:\u002Fgame-engine\u002Fdata\u002Fsaves":1108,"navigation":1119},{"id":4,"title":5,"body":6,"description":1101,"extension":1102,"meta":1103,"navigation":131,"path":1104,"seo":1105,"stem":1106,"__hash__":1107},"docs\u002F01.game-engine\u002F07.data\u002F02.saves.md","Zapisy gry",{"type":7,"value":8,"toc":1094},"minimark",[9,14,67,355,359,367,371,375,396,474,609,632,636,994,998,1087,1090],[10,11,13],"h2",{"id":12},"dwa-repozytoria","Dwa repozytoria",[15,16,17,33],"table",{},[18,19,20],"thead",{},[21,22,23,27,30],"tr",{},[24,25,26],"th",{},"Repozytorium",[24,28,29],{},"Co zapisuje",[24,31,32],{},"Jak",[34,35,36,51],"tbody",{},[21,37,38,45,48],{},[39,40,41],"td",{},[42,43,44],"code",{},"ProjectRepository",[39,46,47],{},"Projekt gry (edytor)",[39,49,50],{},"Atomowo: tmp → odczyt zwrotny → backup → commit",[21,52,53,58,61],{},[39,54,55],{},[42,56,57],{},"PlayerSaveRepository",[39,59,60],{},"Stan gracza (sloty)",[39,62,63,64],{},"Klucz ",[42,65,66],{},"playerId + slot",[68,69,74],"pre",{"className":70,"code":71,"language":72,"meta":73,"style":73},"language-ts shiki shiki-themes github-light github-dark","import {\n  ProjectRepository,\n  PlayerSaveRepository,\n  LocalStorageStore,\n  IndexedDbStore\n} from '@engine'\n\nconst projectRepo = new ProjectRepository(new IndexedDbStore({ database: 'mygame' }))\nawait projectRepo.save(project)\nconst loaded = await projectRepo.load()\nconst backup = await projectRepo.restoreBackup()\n\nconst saves = new PlayerSaveRepository(new LocalStorageStore('mygame:'))\nawait saves.save('player-1', 'slot-1', { level: 4, score: 1280, collected: ['c1', 'c3'] })\nconst state = await saves.load('player-1', 'slot-1')\nawait saves.remove('player-1', 'slot-1')\n","ts","",[42,75,76,89,95,101,107,113,126,133,171,186,207,226,231,261,308,335],{"__ignoreMap":73},[77,78,81,85],"span",{"class":79,"line":80},"line",1,[77,82,84],{"class":83},"szBVR","import",[77,86,88],{"class":87},"sVt8B"," {\n",[77,90,92],{"class":79,"line":91},2,[77,93,94],{"class":87},"  ProjectRepository,\n",[77,96,98],{"class":79,"line":97},3,[77,99,100],{"class":87},"  PlayerSaveRepository,\n",[77,102,104],{"class":79,"line":103},4,[77,105,106],{"class":87},"  LocalStorageStore,\n",[77,108,110],{"class":79,"line":109},5,[77,111,112],{"class":87},"  IndexedDbStore\n",[77,114,116,119,122],{"class":79,"line":115},6,[77,117,118],{"class":87},"} ",[77,120,121],{"class":83},"from",[77,123,125],{"class":124},"sZZnC"," '@engine'\n",[77,127,129],{"class":79,"line":128},7,[77,130,132],{"emptyLinePlaceholder":131},true,"\n",[77,134,136,139,143,146,149,153,156,159,162,165,168],{"class":79,"line":135},8,[77,137,138],{"class":83},"const",[77,140,142],{"class":141},"sj4cs"," projectRepo",[77,144,145],{"class":83}," =",[77,147,148],{"class":83}," new",[77,150,152],{"class":151},"sScJk"," ProjectRepository",[77,154,155],{"class":87},"(",[77,157,158],{"class":83},"new",[77,160,161],{"class":151}," IndexedDbStore",[77,163,164],{"class":87},"({ database: ",[77,166,167],{"class":124},"'mygame'",[77,169,170],{"class":87}," }))\n",[77,172,174,177,180,183],{"class":79,"line":173},9,[77,175,176],{"class":83},"await",[77,178,179],{"class":87}," projectRepo.",[77,181,182],{"class":151},"save",[77,184,185],{"class":87},"(project)\n",[77,187,189,191,194,196,199,201,204],{"class":79,"line":188},10,[77,190,138],{"class":83},[77,192,193],{"class":141}," loaded",[77,195,145],{"class":83},[77,197,198],{"class":83}," await",[77,200,179],{"class":87},[77,202,203],{"class":151},"load",[77,205,206],{"class":87},"()\n",[77,208,210,212,215,217,219,221,224],{"class":79,"line":209},11,[77,211,138],{"class":83},[77,213,214],{"class":141}," backup",[77,216,145],{"class":83},[77,218,198],{"class":83},[77,220,179],{"class":87},[77,222,223],{"class":151},"restoreBackup",[77,225,206],{"class":87},[77,227,229],{"class":79,"line":228},12,[77,230,132],{"emptyLinePlaceholder":131},[77,232,234,236,239,241,243,246,248,250,253,255,258],{"class":79,"line":233},13,[77,235,138],{"class":83},[77,237,238],{"class":141}," saves",[77,240,145],{"class":83},[77,242,148],{"class":83},[77,244,245],{"class":151}," PlayerSaveRepository",[77,247,155],{"class":87},[77,249,158],{"class":83},[77,251,252],{"class":151}," LocalStorageStore",[77,254,155],{"class":87},[77,256,257],{"class":124},"'mygame:'",[77,259,260],{"class":87},"))\n",[77,262,264,266,269,271,273,276,279,282,285,288,291,294,297,300,302,305],{"class":79,"line":263},14,[77,265,176],{"class":83},[77,267,268],{"class":87}," saves.",[77,270,182],{"class":151},[77,272,155],{"class":87},[77,274,275],{"class":124},"'player-1'",[77,277,278],{"class":87},", ",[77,280,281],{"class":124},"'slot-1'",[77,283,284],{"class":87},", { level: ",[77,286,287],{"class":141},"4",[77,289,290],{"class":87},", score: ",[77,292,293],{"class":141},"1280",[77,295,296],{"class":87},", collected: [",[77,298,299],{"class":124},"'c1'",[77,301,278],{"class":87},[77,303,304],{"class":124},"'c3'",[77,306,307],{"class":87},"] })\n",[77,309,311,313,316,318,320,322,324,326,328,330,332],{"class":79,"line":310},15,[77,312,138],{"class":83},[77,314,315],{"class":141}," state",[77,317,145],{"class":83},[77,319,198],{"class":83},[77,321,268],{"class":87},[77,323,203],{"class":151},[77,325,155],{"class":87},[77,327,275],{"class":124},[77,329,278],{"class":87},[77,331,281],{"class":124},[77,333,334],{"class":87},")\n",[77,336,338,340,342,345,347,349,351,353],{"class":79,"line":337},16,[77,339,176],{"class":83},[77,341,268],{"class":87},[77,343,344],{"class":151},"remove",[77,346,155],{"class":87},[77,348,275],{"class":124},[77,350,278],{"class":87},[77,352,281],{"class":124},[77,354,334],{"class":87},[10,356,358],{"id":357},"atomowy-zapis-projektu","Atomowy zapis projektu",[68,360,365],{"className":361,"code":363,"language":364,"meta":73},[362],"language-text","tmp → odczyt zwrotny → backup → commit\n","text",[42,366,363],{"__ignoreMap":73},[368,369,370],"p",{},"Zapis najpierw trafia do pliku tymczasowego, jest odczytywany z powrotem dla weryfikacji, poprzednia wersja staje się backupem, a dopiero potem następuje commit. Przerwanie w dowolnym momencie nie zostawia uszkodzonego projektu.",[10,372,374],{"id":373},"backendy-savestore","Backendy SaveStore",[368,376,377,380,381,278,384,278,387,278,389,278,392,395],{},[42,378,379],{},"SaveStore"," to kontrakt pięciu metod: ",[42,382,383],{},"read",[42,385,386],{},"write",[42,388,344],{},[42,390,391],{},"keys",[42,393,394],{},"clear",".",[15,397,398,408],{},[18,399,400],{},[21,401,402,405],{},[24,403,404],{},"Backend",[24,406,407],{},"Zastosowanie",[34,409,410,420,430,440,450,464],{},[21,411,412,417],{},[39,413,414],{},[42,415,416],{},"MemoryStore",[39,418,419],{},"Testy, tryb incognito",[21,421,422,427],{},[39,423,424],{},[42,425,426],{},"LocalStorageStore(prefix = \"b2d:\")",[39,428,429],{},"Proste zapisy w przeglądarce",[21,431,432,437],{},[39,433,434],{},[42,435,436],{},"IndexedDbStore({ database?, store? })",[39,438,439],{},"Duże zapisy, projekt edytora",[21,441,442,447],{},[39,443,444],{},[42,445,446],{},"FileSystemStore(baseDir)",[39,448,449],{},"Node \u002F Electron",[21,451,452,457],{},[39,453,454],{},[42,455,456],{},"HttpStore({ endpoint, headers? })",[39,458,459,460,463],{},"Zapisy na serwerze (",[42,461,462],{},"\u002Fv1\u002Fentries",")",[21,465,466,471],{},[39,467,468],{},[42,469,470],{},"SqlSaveStore(client, { dialect, table? })",[39,472,473],{},"PostgreSQL \u002F MySQL",[68,475,477],{"className":70,"code":476,"language":72,"meta":73,"style":73},"import { MemoryStore, FileSystemStore, HttpStore, SqlSaveStore, sqlSchema } from '@engine'\n\nconst memory = new MemoryStore()\nconst fs = new FileSystemStore('.\u002Fsaves')\nconst http = new HttpStore({ endpoint: 'https:\u002F\u002Fapi.example.com\u002Fv1\u002Fentries' })\n\nconst sql = new SqlSaveStore(pgClient, { dialect: 'postgres', table: 'player_saves' })\nconst ddl = sqlSchema({ dialect: 'postgres', table: 'player_saves' })\n",[42,478,479,490,494,510,531,554,558,586],{"__ignoreMap":73},[77,480,481,483,486,488],{"class":79,"line":80},[77,482,84],{"class":83},[77,484,485],{"class":87}," { MemoryStore, FileSystemStore, HttpStore, SqlSaveStore, sqlSchema } ",[77,487,121],{"class":83},[77,489,125],{"class":124},[77,491,492],{"class":79,"line":91},[77,493,132],{"emptyLinePlaceholder":131},[77,495,496,498,501,503,505,508],{"class":79,"line":97},[77,497,138],{"class":83},[77,499,500],{"class":141}," memory",[77,502,145],{"class":83},[77,504,148],{"class":83},[77,506,507],{"class":151}," MemoryStore",[77,509,206],{"class":87},[77,511,512,514,517,519,521,524,526,529],{"class":79,"line":103},[77,513,138],{"class":83},[77,515,516],{"class":141}," fs",[77,518,145],{"class":83},[77,520,148],{"class":83},[77,522,523],{"class":151}," FileSystemStore",[77,525,155],{"class":87},[77,527,528],{"class":124},"'.\u002Fsaves'",[77,530,334],{"class":87},[77,532,533,535,538,540,542,545,548,551],{"class":79,"line":109},[77,534,138],{"class":83},[77,536,537],{"class":141}," http",[77,539,145],{"class":83},[77,541,148],{"class":83},[77,543,544],{"class":151}," HttpStore",[77,546,547],{"class":87},"({ endpoint: ",[77,549,550],{"class":124},"'https:\u002F\u002Fapi.example.com\u002Fv1\u002Fentries'",[77,552,553],{"class":87}," })\n",[77,555,556],{"class":79,"line":115},[77,557,132],{"emptyLinePlaceholder":131},[77,559,560,562,565,567,569,572,575,578,581,584],{"class":79,"line":128},[77,561,138],{"class":83},[77,563,564],{"class":141}," sql",[77,566,145],{"class":83},[77,568,148],{"class":83},[77,570,571],{"class":151}," SqlSaveStore",[77,573,574],{"class":87},"(pgClient, { dialect: ",[77,576,577],{"class":124},"'postgres'",[77,579,580],{"class":87},", table: ",[77,582,583],{"class":124},"'player_saves'",[77,585,553],{"class":87},[77,587,588,590,593,595,598,601,603,605,607],{"class":79,"line":135},[77,589,138],{"class":83},[77,591,592],{"class":141}," ddl",[77,594,145],{"class":83},[77,596,597],{"class":151}," sqlSchema",[77,599,600],{"class":87},"({ dialect: ",[77,602,577],{"class":124},[77,604,580],{"class":87},[77,606,583],{"class":124},[77,608,553],{"class":87},[610,611,614],"callout",{"title":612,"type":613},"Zero sterowników w bundlu","info",[368,615,616,619,620,623,624,627,628,631],{},[42,617,618],{},"SqlSaveStore"," przyjmuje dowolny obiekt z ",[42,621,622],{},"query(sql, params)",". Dzięki wstrzykiwanemu klientowi w bundlu gry nie ma ",[42,625,626],{},"pg"," ani ",[42,629,630],{},"mysql2"," — sterownik żyje po stronie serwera.",[10,633,635],{"id":634},"przykład-system-slotów-zapisu","Przykład: system slotów zapisu",[68,637,639],{"className":70,"code":638,"language":72,"meta":73,"style":73},"class GameScene extends Scene {\n  private saves = new PlayerSaveRepository(new IndexedDbStore({ database: 'mygame' }))\n  private playerId = 'player-1'\n\n  async saveGame(slot: string) {\n    await this.saves.save(this.playerId, slot, {\n      level: this.currentLevel,\n      score: this.score,\n      collected: this.collected,\n      position: { x: this.player.x, y: this.player.y },\n      savedAt: Date.now()\n    })\n  }\n\n  async loadGame(slot: string) {\n    const state = await this.saves.load\u003CPlayerState>(this.playerId, slot)\n    if (!state) return false\n    this.currentLevel = state.level\n    this.score = state.score\n    this.collected = state.collected\n    this.player.setPosition(state.position.x, state.position.y)\n    return true\n  }\n\n  shutdown() {\n    void this.saveGame('autosave')\n  }\n}\n",[42,640,641,657,683,695,699,721,742,752,762,772,787,797,802,807,811,828,859,880,895,908,921,935,944,949,954,963,983,988],{"__ignoreMap":73},[77,642,643,646,649,652,655],{"class":79,"line":80},[77,644,645],{"class":83},"class",[77,647,648],{"class":151}," GameScene",[77,650,651],{"class":83}," extends",[77,653,654],{"class":151}," Scene",[77,656,88],{"class":87},[77,658,659,662,665,667,669,671,673,675,677,679,681],{"class":79,"line":91},[77,660,661],{"class":83},"  private",[77,663,238],{"class":664},"s4XuR",[77,666,145],{"class":83},[77,668,148],{"class":83},[77,670,245],{"class":151},[77,672,155],{"class":87},[77,674,158],{"class":83},[77,676,161],{"class":151},[77,678,164],{"class":87},[77,680,167],{"class":124},[77,682,170],{"class":87},[77,684,685,687,690,692],{"class":79,"line":97},[77,686,661],{"class":83},[77,688,689],{"class":664}," playerId",[77,691,145],{"class":83},[77,693,694],{"class":124}," 'player-1'\n",[77,696,697],{"class":79,"line":103},[77,698,132],{"emptyLinePlaceholder":131},[77,700,701,704,707,709,712,715,718],{"class":79,"line":109},[77,702,703],{"class":83},"  async",[77,705,706],{"class":151}," saveGame",[77,708,155],{"class":87},[77,710,711],{"class":664},"slot",[77,713,714],{"class":83},":",[77,716,717],{"class":141}," string",[77,719,720],{"class":87},") {\n",[77,722,723,726,729,732,734,736,739],{"class":79,"line":115},[77,724,725],{"class":83},"    await",[77,727,728],{"class":141}," this",[77,730,731],{"class":87},".saves.",[77,733,182],{"class":151},[77,735,155],{"class":87},[77,737,738],{"class":141},"this",[77,740,741],{"class":87},".playerId, slot, {\n",[77,743,744,747,749],{"class":79,"line":128},[77,745,746],{"class":87},"      level: ",[77,748,738],{"class":141},[77,750,751],{"class":87},".currentLevel,\n",[77,753,754,757,759],{"class":79,"line":135},[77,755,756],{"class":87},"      score: ",[77,758,738],{"class":141},[77,760,761],{"class":87},".score,\n",[77,763,764,767,769],{"class":79,"line":173},[77,765,766],{"class":87},"      collected: ",[77,768,738],{"class":141},[77,770,771],{"class":87},".collected,\n",[77,773,774,777,779,782,784],{"class":79,"line":188},[77,775,776],{"class":87},"      position: { x: ",[77,778,738],{"class":141},[77,780,781],{"class":87},".player.x, y: ",[77,783,738],{"class":141},[77,785,786],{"class":87},".player.y },\n",[77,788,789,792,795],{"class":79,"line":209},[77,790,791],{"class":87},"      savedAt: Date.",[77,793,794],{"class":151},"now",[77,796,206],{"class":87},[77,798,799],{"class":79,"line":228},[77,800,801],{"class":87},"    })\n",[77,803,804],{"class":79,"line":233},[77,805,806],{"class":87},"  }\n",[77,808,809],{"class":79,"line":263},[77,810,132],{"emptyLinePlaceholder":131},[77,812,813,815,818,820,822,824,826],{"class":79,"line":310},[77,814,703],{"class":83},[77,816,817],{"class":151}," loadGame",[77,819,155],{"class":87},[77,821,711],{"class":664},[77,823,714],{"class":83},[77,825,717],{"class":141},[77,827,720],{"class":87},[77,829,830,833,835,837,839,841,843,845,848,851,854,856],{"class":79,"line":337},[77,831,832],{"class":83},"    const",[77,834,315],{"class":141},[77,836,145],{"class":83},[77,838,198],{"class":83},[77,840,728],{"class":141},[77,842,731],{"class":87},[77,844,203],{"class":151},[77,846,847],{"class":87},"\u003C",[77,849,850],{"class":151},"PlayerState",[77,852,853],{"class":87},">(",[77,855,738],{"class":141},[77,857,858],{"class":87},".playerId, slot)\n",[77,860,862,865,868,871,874,877],{"class":79,"line":861},17,[77,863,864],{"class":83},"    if",[77,866,867],{"class":87}," (",[77,869,870],{"class":83},"!",[77,872,873],{"class":87},"state) ",[77,875,876],{"class":83},"return",[77,878,879],{"class":141}," false\n",[77,881,883,886,889,892],{"class":79,"line":882},18,[77,884,885],{"class":141},"    this",[77,887,888],{"class":87},".currentLevel ",[77,890,891],{"class":83},"=",[77,893,894],{"class":87}," state.level\n",[77,896,898,900,903,905],{"class":79,"line":897},19,[77,899,885],{"class":141},[77,901,902],{"class":87},".score ",[77,904,891],{"class":83},[77,906,907],{"class":87}," state.score\n",[77,909,911,913,916,918],{"class":79,"line":910},20,[77,912,885],{"class":141},[77,914,915],{"class":87},".collected ",[77,917,891],{"class":83},[77,919,920],{"class":87}," state.collected\n",[77,922,924,926,929,932],{"class":79,"line":923},21,[77,925,885],{"class":141},[77,927,928],{"class":87},".player.",[77,930,931],{"class":151},"setPosition",[77,933,934],{"class":87},"(state.position.x, state.position.y)\n",[77,936,938,941],{"class":79,"line":937},22,[77,939,940],{"class":83},"    return",[77,942,943],{"class":141}," true\n",[77,945,947],{"class":79,"line":946},23,[77,948,806],{"class":87},[77,950,952],{"class":79,"line":951},24,[77,953,132],{"emptyLinePlaceholder":131},[77,955,957,960],{"class":79,"line":956},25,[77,958,959],{"class":151},"  shutdown",[77,961,962],{"class":87},"() {\n",[77,964,966,969,971,973,976,978,981],{"class":79,"line":965},26,[77,967,968],{"class":83},"    void",[77,970,728],{"class":141},[77,972,395],{"class":87},[77,974,975],{"class":151},"saveGame",[77,977,155],{"class":87},[77,979,980],{"class":124},"'autosave'",[77,982,334],{"class":87},[77,984,986],{"class":79,"line":985},27,[77,987,806],{"class":87},[77,989,991],{"class":79,"line":990},28,[77,992,993],{"class":87},"}\n",[10,995,997],{"id":996},"przykład-zapisy-serwerowe","Przykład: zapisy serwerowe",[68,999,1001],{"className":70,"code":1000,"language":72,"meta":73,"style":73},"const store = new HttpStore({\n  endpoint: 'https:\u002F\u002Fapi.example.com\u002Fv1\u002Fentries',\n  headers: { Authorization: `Bearer ${token}` }\n})\n\nconst saves = new PlayerSaveRepository(store)\nawait saves.save(userId, 'cloud', playerState)\n",[42,1002,1003,1019,1029,1046,1051,1055,1070],{"__ignoreMap":73},[77,1004,1005,1007,1010,1012,1014,1016],{"class":79,"line":80},[77,1006,138],{"class":83},[77,1008,1009],{"class":141}," store",[77,1011,145],{"class":83},[77,1013,148],{"class":83},[77,1015,544],{"class":151},[77,1017,1018],{"class":87},"({\n",[77,1020,1021,1024,1026],{"class":79,"line":91},[77,1022,1023],{"class":87},"  endpoint: ",[77,1025,550],{"class":124},[77,1027,1028],{"class":87},",\n",[77,1030,1031,1034,1037,1040,1043],{"class":79,"line":97},[77,1032,1033],{"class":87},"  headers: { Authorization: ",[77,1035,1036],{"class":124},"`Bearer ${",[77,1038,1039],{"class":87},"token",[77,1041,1042],{"class":124},"}`",[77,1044,1045],{"class":87}," }\n",[77,1047,1048],{"class":79,"line":103},[77,1049,1050],{"class":87},"})\n",[77,1052,1053],{"class":79,"line":109},[77,1054,132],{"emptyLinePlaceholder":131},[77,1056,1057,1059,1061,1063,1065,1067],{"class":79,"line":115},[77,1058,138],{"class":83},[77,1060,238],{"class":141},[77,1062,145],{"class":83},[77,1064,148],{"class":83},[77,1066,245],{"class":151},[77,1068,1069],{"class":87},"(store)\n",[77,1071,1072,1074,1076,1078,1081,1084],{"class":79,"line":128},[77,1073,176],{"class":83},[77,1075,268],{"class":87},[77,1077,182],{"class":151},[77,1079,1080],{"class":87},"(userId, ",[77,1082,1083],{"class":124},"'cloud'",[77,1085,1086],{"class":87},", playerState)\n",[368,1088,1089],{},"Ten sam kod działa lokalnie i w chmurze — zmienia się tylko backend.",[1091,1092,1093],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":73,"searchDepth":97,"depth":97,"links":1095},[1096,1097,1098,1099,1100],{"id":12,"depth":91,"text":13},{"id":357,"depth":91,"text":358},{"id":373,"depth":91,"text":374},{"id":634,"depth":91,"text":635},{"id":996,"depth":91,"text":997},"ProjectRepository z atomowym zapisem, PlayerSaveRepository i sześć backendów SaveStore — od localStorage po SQL.","md",{},"\u002Fgame-engine\u002Fdata\u002Fsaves",{"title":5,"description":1101},"01.game-engine\u002F07.data\u002F02.saves","CtmFPg70lv6K9VFJQOjWyjYCIGCHzYI0rhBaECZNjQk",[1109,1114],{"title":1110,"path":1111,"stem":1112,"description":1113,"children":-1},"Format projektu","\u002Fgame-engine\u002Fdata\u002Fproject-format","01.game-engine\u002F07.data\u002F01.project-format","Wersjonowany JSON projektu (formatVersion 2), walidacja, migracje, import\u002Feksport z sumą kontrolną FNV-1a.",{"title":1115,"path":1116,"stem":1117,"description":1118,"children":-1},"Pluginy","\u002Fgame-engine\u002Fadvanced\u002Fplugins","01.game-engine\u002F08.advanced\u002F01.plugins","PluginHost, manifest, uprawnienia, punkty rozszerzeń, zależności z detekcją cykli i budżety błędów. Jak pisać pluginy bezpiecznie.",[1120,1231,1292],{"title":1121,"path":1122,"stem":1123,"children":1124},"2D Game Engine","\u002Fgame-engine","01.game-engine\u002F01.index",[1125,1127,1131,1135,1139,1165,1194,1201,1219,1223,1227],{"title":1126,"path":1122,"stem":1123},"Przegląd",{"title":1128,"path":1129,"stem":1130},"Szybki start","\u002Fgame-engine\u002Fgetting-started","01.game-engine\u002F02.getting-started",{"title":1132,"path":1133,"stem":1134},"Konfiguracja","\u002Fgame-engine\u002Fconfiguration","01.game-engine\u002F03.configuration",{"title":1136,"path":1137,"stem":1138},"Architektura","\u002Fgame-engine\u002Farchitecture","01.game-engine\u002F04.architecture",{"title":1140,"path":1141,"stem":1142,"children":1143,"page":1164},"Rdzeń","\u002Fgame-engine\u002Fcore","01.game-engine\u002F05.core",[1144,1148,1152,1156,1160],{"title":1145,"path":1146,"stem":1147},"Silnik i cykl życia","\u002Fgame-engine\u002Fcore\u002Fengine","01.game-engine\u002F05.core\u002F01.engine",{"title":1149,"path":1150,"stem":1151},"Czas i pętla gry","\u002Fgame-engine\u002Fcore\u002Ftime","01.game-engine\u002F05.core\u002F02.time",{"title":1153,"path":1154,"stem":1155},"Sceny","\u002Fgame-engine\u002Fcore\u002Fscenes","01.game-engine\u002F05.core\u002F03.scenes",{"title":1157,"path":1158,"stem":1159},"Obiekty i komponenty","\u002Fgame-engine\u002Fcore\u002Fobjects","01.game-engine\u002F05.core\u002F04.objects",{"title":1161,"path":1162,"stem":1163},"Zdarzenia i harmonogram","\u002Fgame-engine\u002Fcore\u002Fevents","01.game-engine\u002F05.core\u002F05.events",false,{"title":1166,"path":1167,"stem":1168,"children":1169,"page":1164},"Systemy","\u002Fgame-engine\u002Fsystems","01.game-engine\u002F06.systems",[1170,1174,1178,1182,1186,1190],{"title":1171,"path":1172,"stem":1173},"Zasoby (AssetManager)","\u002Fgame-engine\u002Fsystems\u002Fassets","01.game-engine\u002F06.systems\u002F01.assets",{"title":1175,"path":1176,"stem":1177},"Wejście (InputManager)","\u002Fgame-engine\u002Fsystems\u002Finput","01.game-engine\u002F06.systems\u002F02.input",{"title":1179,"path":1180,"stem":1181},"Fizyka (PhysicsManager)","\u002Fgame-engine\u002Fsystems\u002Fphysics","01.game-engine\u002F06.systems\u002F03.physics",{"title":1183,"path":1184,"stem":1185},"Kamera (CameraManager)","\u002Fgame-engine\u002Fsystems\u002Fcamera","01.game-engine\u002F06.systems\u002F04.camera",{"title":1187,"path":1188,"stem":1189},"Audio (AudioManager)","\u002Fgame-engine\u002Fsystems\u002Faudio","01.game-engine\u002F06.systems\u002F05.audio",{"title":1191,"path":1192,"stem":1193},"Tweeny i easing","\u002Fgame-engine\u002Fsystems\u002Ftweens","01.game-engine\u002F06.systems\u002F06.tweens",{"title":1195,"path":1196,"stem":1197,"children":1198,"page":1164},"Dane i zapisy","\u002Fgame-engine\u002Fdata","01.game-engine\u002F07.data",[1199,1200],{"title":1110,"path":1111,"stem":1112},{"title":5,"path":1104,"stem":1106},{"title":1202,"path":1203,"stem":1204,"children":1205,"page":1164},"Zaawansowane","\u002Fgame-engine\u002Fadvanced","01.game-engine\u002F08.advanced",[1206,1207,1211,1215],{"title":1115,"path":1116,"stem":1117},{"title":1208,"path":1209,"stem":1210},"WebAssembly","\u002Fgame-engine\u002Fadvanced\u002Fwasm","01.game-engine\u002F08.advanced\u002F02.wasm",{"title":1212,"path":1213,"stem":1214},"Debugowanie","\u002Fgame-engine\u002Fadvanced\u002Fdebugging","01.game-engine\u002F08.advanced\u002F03.debugging",{"title":1216,"path":1217,"stem":1218},"Wydajność i benchmarki","\u002Fgame-engine\u002Fadvanced\u002Fperformance","01.game-engine\u002F08.advanced\u002F04.performance",{"title":1220,"path":1221,"stem":1222},"Wdrożenie","\u002Fgame-engine\u002Fdeployment","01.game-engine\u002F09.deployment",{"title":1224,"path":1225,"stem":1226},"Przykłady","\u002Fgame-engine\u002Fexamples","01.game-engine\u002F10.examples",{"title":1228,"path":1229,"stem":1230},"Decyzje architektoniczne","\u002Fgame-engine\u002Fadr","01.game-engine\u002F11.adr",{"title":1232,"path":1233,"stem":1234,"children":1235},"Reverse Proxy","\u002Freverse-proxy","02.reverse-proxy\u002F01.index",[1236,1237,1240,1243,1264],{"title":1126,"path":1233,"stem":1234},{"title":1128,"path":1238,"stem":1239},"\u002Freverse-proxy\u002Fgetting-started","02.reverse-proxy\u002F02.getting-started",{"title":1132,"path":1241,"stem":1242},"\u002Freverse-proxy\u002Fconfiguration","02.reverse-proxy\u002F03.configuration",{"title":1244,"path":1245,"stem":1246,"children":1247,"page":1164},"Ruch i odporność","\u002Freverse-proxy\u002Ftraffic","02.reverse-proxy\u002F04.traffic",[1248,1252,1256,1260],{"title":1249,"path":1250,"stem":1251},"Load balancing","\u002Freverse-proxy\u002Ftraffic\u002Fload-balancing","02.reverse-proxy\u002F04.traffic\u002F01.load-balancing",{"title":1253,"path":1254,"stem":1255},"Health checks","\u002Freverse-proxy\u002Ftraffic\u002Fhealth-checks","02.reverse-proxy\u002F04.traffic\u002F02.health-checks",{"title":1257,"path":1258,"stem":1259},"Circuit breaker i retry","\u002Freverse-proxy\u002Ftraffic\u002Fresilience","02.reverse-proxy\u002F04.traffic\u002F03.resilience",{"title":1261,"path":1262,"stem":1263},"Rate limiting","\u002Freverse-proxy\u002Ftraffic\u002Frate-limiting","02.reverse-proxy\u002F04.traffic\u002F04.rate-limiting",{"title":1265,"path":1266,"stem":1267,"children":1268,"page":1164},"Operacje i wdrożenie","\u002Freverse-proxy\u002Foperations","02.reverse-proxy\u002F05.operations",[1269,1273,1277,1281,1284,1288],{"title":1270,"path":1271,"stem":1272},"Admin API","\u002Freverse-proxy\u002Foperations\u002Fadmin-api","02.reverse-proxy\u002F05.operations\u002F01.admin-api",{"title":1274,"path":1275,"stem":1276},"Metryki i monitoring","\u002Freverse-proxy\u002Foperations\u002Fobservability","02.reverse-proxy\u002F05.operations\u002F02.observability",{"title":1278,"path":1279,"stem":1280},"Bezpieczeństwo","\u002Freverse-proxy\u002Foperations\u002Fsecurity","02.reverse-proxy\u002F05.operations\u002F03.security",{"title":1220,"path":1282,"stem":1283},"\u002Freverse-proxy\u002Foperations\u002Fdeployment","02.reverse-proxy\u002F05.operations\u002F04.deployment",{"title":1285,"path":1286,"stem":1287},"Benchmarki","\u002Freverse-proxy\u002Foperations\u002Fbenchmarks","02.reverse-proxy\u002F05.operations\u002F05.benchmarks",{"title":1289,"path":1290,"stem":1291},"Troubleshooting","\u002Freverse-proxy\u002Foperations\u002Ftroubleshooting","02.reverse-proxy\u002F05.operations\u002F06.troubleshooting",{"title":1293,"path":1294,"stem":1295,"children":1296},"Vector Engine","\u002Fvector-engine","03.vector-engine\u002F01.index",[1297,1298,1301,1322,1335,1355],{"title":1126,"path":1294,"stem":1295},{"title":1128,"path":1299,"stem":1300},"\u002Fvector-engine\u002Fgetting-started","03.vector-engine\u002F02.getting-started",{"title":1302,"path":1303,"stem":1304,"children":1305,"page":1164},"Scena","\u002Fvector-engine\u002Fscene","03.vector-engine\u002F03.scene",[1306,1310,1314,1318],{"title":1307,"path":1308,"stem":1309},"Format sceny 1.0","\u002Fvector-engine\u002Fscene\u002Fscene-format","03.vector-engine\u002F03.scene\u002F01.scene-format",{"title":1311,"path":1312,"stem":1313},"Obiekty sceny","\u002Fvector-engine\u002Fscene\u002Fobjects","03.vector-engine\u002F03.scene\u002F02.objects",{"title":1315,"path":1316,"stem":1317},"Gradienty i warstwy","\u002Fvector-engine\u002Fscene\u002Fgradients-layers","03.vector-engine\u002F03.scene\u002F03.gradients-layers",{"title":1319,"path":1320,"stem":1321},"Przykłady scen","\u002Fvector-engine\u002Fscene\u002Fexamples","03.vector-engine\u002F03.scene\u002F04.examples",{"title":1323,"path":1324,"stem":1325,"children":1326,"page":1164},"Eksport","\u002Fvector-engine\u002Fexport","03.vector-engine\u002F04.export",[1327,1331],{"title":1328,"path":1329,"stem":1330},"Formaty eksportu","\u002Fvector-engine\u002Fexport\u002Fexport-formats","03.vector-engine\u002F04.export\u002F01.export-formats",{"title":1332,"path":1333,"stem":1334},"Proces eksportu","\u002Fvector-engine\u002Fexport\u002Fexport-workflow","03.vector-engine\u002F04.export\u002F02.export-workflow",{"title":1336,"path":1337,"stem":1338,"children":1339,"page":1164},"Wnętrze silnika","\u002Fvector-engine\u002Finternals","03.vector-engine\u002F05.internals",[1340,1343,1347,1351],{"title":1136,"path":1341,"stem":1342},"\u002Fvector-engine\u002Finternals\u002Farchitecture","03.vector-engine\u002F05.internals\u002F01.architecture",{"title":1344,"path":1345,"stem":1346},"WebAssembly i workery","\u002Fvector-engine\u002Finternals\u002Fwasm","03.vector-engine\u002F05.internals\u002F02.wasm",{"title":1348,"path":1349,"stem":1350},"Workspace i panele","\u002Fvector-engine\u002Finternals\u002Fworkspace","03.vector-engine\u002F05.internals\u002F03.workspace",{"title":1352,"path":1353,"stem":1354},"Breakpointy","\u002Fvector-engine\u002Finternals\u002Fbreakpoints","03.vector-engine\u002F05.internals\u002F04.breakpoints",{"title":1356,"path":1357,"stem":1358},"Wdrożenie na Vercel","\u002Fvector-engine\u002Fdeployment","03.vector-engine\u002F06.deployment",1793986307750]