[웹 어셈블리, WSAM] Persisting data with Emscripten : Emscripten으로 데이터 유지하기

Persisting data with Emscripten

When porting your game to Emscripten, you will soon enough notice that the default virtual file system it use doesn’t persist data, everything you write in a file is lost from one session to another. Hopefully, Emscripten has a specific file system, called IDBFS which persist your data (using the HTML5 API Indexed Db). Now, it’s important to note that you have to call manually the sync operation, and also to handle the delay between the moment you call for synchronization and the moment data are effectively synchronized, since the API is asynchronous. For more details on Emscripten File System API, the official website offer a lot of informations :
Emscripten API

On my existing C games, I persist data through SQLite. The huge advantage of SQLite is that you can use SQL language to select / manage your data and take advantage of most DBMS functionalities without the need to have any kind of server running in the background, since everything in SQLite is saved on a single db file.

Using IDBFS, it’s possible to keep your entire existing SQLite management code, the only thing you need is to call Emscripten sync API when needed to persist any changes:

Initialisation of the IDBFS filesystem :

EM_ASM(
       //create your directory where we keep our persistent data
       FS.mkdir('/persistent_data'); 

       //mount persistent directory as IDBFS
       FS.mount(IDBFS,{},'/persistent_data');

       Module.print("start file sync..");
       //flag to check when data are synchronized
       Module.syncdone = 0;

       //populate persistent_data directory with existing persistent source data 
      //stored with Indexed Db
      //first parameter = "true" mean synchronize from Indexed Db to 
      //Emscripten file system,
      // "false" mean synchronize from Emscripten file system to Indexed Db
      //second parameter = function called when data are synchronized
      FS.syncfs(true, function(err) {
                       assert(!err);
                       Module.print("end file sync..");
                       Module.syncdone = 1;
      });
);

(the EM_ASM macro allow us to call JavaScript code within c)

At the first run, the “persistent_data” folder is always empty, you can’t mount a directory that is already mounted with the default virtual file system.

After synchronisation is done, you can either start using the existing files that are now into the “persistent_data” folder, or add the base data into your folder if it’s the first time a player run your game.

if(!save_mngr.ready)
{
     //check the Module.syncdone flag value
    if(emscripten_run_script_int("Module.syncdone") == 1)
    {
         //check that our base SQLite data exist, if not copy it 
        //in the "persistent_data" folder
        FILE* file = fopen(save_path,"r");

       if(file == NULL)
       {
           logprint("save.db file doesn't exist in file system, copying it...");
           size_t size;
           //copy file
           //in this case I copy a base SQLite file into my persistent folder,
           // "base_data" is a folder in the default Emscripten file system
           unsigned char* buffer = get_resx_content(&game_state->resx_mngr,"/base_data/save.db",&size,NULL);

           file = fopen(save_path,"w");

           fwrite(buffer,sizeof(unsigned char),size,file);
           fclose(file);

           //persist Emscripten current data to Indexed Db
           EM_ASM(
                  Module.print("Start File sync..");
                  Module.syncdone = 0;
                  FS.syncfs(false, function(err) {
                                    assert(!err);
                                   Module.print("End File sync..");
                                   Module.syncdone = 1;
                                   });
            );
        }
        else
        {
            fclose(file);
        }

        save_mngr_init(&save_mngr,save_path); //here I load my SQLite file like usual and start using it, the save_mngr.ready flag is now set to true
    }
    else
    {
        return; //I prevent any further code to run as long as the save data are not ready
    }
}

(the save_mngr function is the object that handle all my save data using SQLite)
(this code is put at the beginning of my gameloop function, since you have to wait for data to be synchronized, and that there is no proper way of waiting for code execution with Emscripten (the same way sleep() or a while loop would do on desktop versions))

After that, you can persist any changes to your SQLite file with this code, for example after any data insertion or data update :

EM_ASM(
        //persist changes
        FS.syncfs(false,function (err) {
                          assert(!err);
        });
);

and that’s all! The initialisation code will then load the modified SQLite data next time the player run the game. It’s possible to check Indexed Db content afterwards with Chrome, go to Developments tools > Resources tab > Indexed Db.

[출처] https://uncovergame.com/2015/06/06/persisting-data-with-emscripten/

 

Emscripten으로 데이터 유지하기

게임을 Emscripten으로 포팅할 때, 게임이 사용하는 기본 가상 파일 시스템이 데이터를 유지하지 않고, 파일에 쓴 모든 내용이 한 세션에서 다른 세션으로 이동하면 곧 손실된다는 사실을 알게 될 것입니다. Emscripten에는 데이터를 유지하는(HTML5 API Indexed Db 사용) IDBFS라는 특정 파일 시스템이 있기를 바랍니다. 이제 API가 비동기식이므로 동기화 작업을 수동으로 호출해야 하며 동기화를 호출하는 순간과 데이터가 효과적으로 동기화되는 순간 사이의 지연을 처리해야 한다는 점에 유의하는 것이 중요합니다. Emscripten File System API에 대한 자세한 내용은 공식 웹사이트에서 많은 정보를 제공합니다.
Emscripten API

기존 C 게임에서는 SQLite를 통해 데이터를 유지합니다. SQLite의 가장 큰 장점은 SQLite의 모든 내용이 단일 db 파일에 저장되므로 SQL 언어를 사용하여 데이터를 선택/관리하고 백그라운드에서 어떤 종류의 서버도 실행할 필요 없이 대부분의 DBMS 기능을 활용할 수 있다는 것입니다. .

IDBFS를 사용하면 기존 SQLite 관리 코드 전체를 유지할 수 있으며, 변경 사항을 유지해야 할 때 Emscripten 동기화 API를 호출하기만 하면 됩니다.

IDBFS 파일 시스템 초기화:

EM_ASM( 
       //영구 데이터를 보관할 디렉터리를 생성합니다. 
       FS.mkdir('/percious_data'); 

       //영구 디렉터리를 IDBFS로 마운트합니다. 
       FS.mount(IDBFS,{},'/percious_data'); 

       Module.print(" start file sync.."); 
       //데이터가 동기화될 때 확인하기 위한 플래그 
       Module.syncdone = 0; 

       //Persistent_data 디렉토리를 기존 영구 소스 데이터로 채웁니다 
      . //인덱스된 Db로 저장됩니다. 
      //첫 번째 매개변수 = "true"는 동기화를 의미합니다. 
      //Emscripten 파일 시스템 으로 인덱싱된 Db , 
      // "false"는 Emscripten 파일 시스템에서 인덱싱된 Db로 동기화를 의미합니다. 
      //두 번째 매개 변수 = 데이터가 동기화될 때 호출되는 함수 
      FS.syncfs(true, function(err) { 
                       주장(!err) ; 
                       Module.print("파일 동기화 종료.."); 
                       Module.syncdone = 1 
      ) 
;

(EM_ASM 매크로를 사용하면 c 내에서 JavaScript 코드를 호출할 수 있습니다)

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

처음 실행 시, “persist_data” 폴더는 항상 비어 있으며, 기본 가상 파일 시스템으로 이미 마운트된 디렉터리는 마운트할 수 없습니다.

동기화가 완료된 후에는 현재 "persist_data" 폴더에 있는 기존 파일을 사용하기 시작하거나, 플레이어가 처음으로 게임을 실행하는 경우 기본 데이터를 폴더에 추가할 수 있습니다.

if(!save_mngr.ready) 
{ 
     //Module.syncdone 플래그 값을 확인합니다. 
    if(emscripten_run_script_int("Module.syncdone") == 1) 
    { 
         //기본 SQLite 데이터가 존재하는지 확인합니다. 복사하지 않은 경우 
        // "persist_data" 폴더 
        FILE* file = fopen(save_path,"r"); 

       if(file == NULL) 
       { 
           logprint("save.db 파일이 파일 시스템에 없습니다. 복사하는 중입니다..."); 
           size_t 사이즈; 
           //파일 복사 
           //이 경우 기본 SQLite 파일을 영구 폴더에 복사합니다. 
           // "base_data"는 기본 Emscripten 파일 시스템의 폴더입니다. 
           unsigned char* buffer = get_resx_content(&game_state->resx_mngr,"/base_data/ save.db",&size,NULL); 

           file = fopen(save_path,"w"); 

           fwrite(버퍼, 크기(부호 없는 문자), 크기, 파일); 
           fclose(파일); 

           //Emscripten 현재 데이터를 인덱스된 Db에 유지 
           EM_ASM( 
                  Module.print("Start File sync.."); 
                  Module.syncdone = 0; 
                  FS.syncfs(false, function(err) { 
                                    주장(!err); 
                                   Module.print ("파일 동기화 종료.."); 
                                   Module.syncdone = 1 
                                   ) 
            ; 
        } 
        else 
        { 
            fclose(파일); 
        } 

        save_mngr_init(&save_mngr,save_path); //여기서 평소처럼 SQLite 파일을 로드하고 사용하기 시작합니다. 이제 save_mngr.ready 플래그가 true로 설정됩니다. 
    } 
    else 
    { 
        return; //저장 데이터가 준비되지 않은 한 더 이상 코드가 실행되지 않도록 합니다 
    . } 
}

(save_mngr 함수는 SQLite를 사용하여 내 모든 저장 데이터를 처리하는 개체입니다.)
(이 코드는 데이터가 동기화될 때까지 기다려야 하고 동기화를 기다리는 적절한 방법이 없기 때문에 내 게임루프 함수의 시작 부분에 배치됩니다. Emscripten을 사용한 코드 실행(데스크톱 버전에서 sleep() 또는 while 루프가 수행하는 것과 동일한 방식))

그 후에는 예를 들어 데이터 삽입이나 데이터 업데이트 후에 이 코드를 사용하여 SQLite 파일에 대한 모든 변경 사항을 유지할 수 있습니다.

EM_ASM( 
        //변경 사항 유지 
        FS.syncfs(false,function (err) { 
                          주장(!err); 
        }); 
);

그리고 그게 다야! 초기화 코드는 다음에 플레이어가 게임을 실행할 때 수정된 SQLite 데이터를 로드합니다. 나중에 Chrome을 사용하여 Indexed Db 콘텐츠를 확인할 수 있습니다. 개발 도구 > 리소스 탭 > Indexed Db로 이동하세요.

[출처] https://uncovergame.com/2015/06/06/persisting-data-with-emscripten/

 

 

 

 

 

 

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
» [웹 어셈블리, WSAM] Persisting data with Emscripten : Emscripten으로 데이터 유지하기 졸리운_곰 2024.04.20 381
12 [웹 어셈블리, WSAM] Porting a Linux Program to Run in Browser using Emscripten : mscripten을 사용하여 브라우저에서 실행되도록 Linux 프로그램 포팅 졸리운_곰 2024.04.20 392
11 [웹 어셈블리, WSAM] An example of emscripten with WebSocket. file 졸리운_곰 2023.12.12 462
10 [웹 어셈블리, WSAM] サーバサイドはWebAssemblyの夢を見るか? – Node.jsでwasmってみた : 서버 측은 WebAssembly의 꿈을 꾸는가? – Node.js에서 wasm 해 보았습니다. file 졸리운_곰 2023.08.27 365
9 [웹 어셈블리 WSAM, webassembly] WebAssembly on the server-side : 서버측 웹어셈블리 file 졸리운_곰 2023.08.27 504
8 [Blazor][WASM] Awesome Blazor file 졸리운_곰 2021.08.15 20070
7 [Blazor][C# .net] Blazor와 C#으로 풀스택 웹 개발하기 file 졸리운_곰 2021.08.15 444
6 [WASM][web assembly] 웹 어셈블리를 보다 쉽게 웹 어플리케이션에 적용하는 방법 file 졸리운_곰 2021.07.19 428
5 Using Blazor, Tensorflow and ML.NET to Identify Images file 졸리운_곰 2021.07.03 529
4 [WASM][WebAssembly] The Top 81 Emscripten Open Source Projects 졸리운_곰 2021.04.19 518
3 [WebAssembly][WSAM] Blazor와 WebAssembly 소개 file 졸리운_곰 2021.03.28 516
2 Webassembly Tutorial using Emscripten file 졸리운_곰 2020.10.24 646
1 [웹어셈블리] Visual Studio 2019와 Emscripten (emcc) 개발 file 졸리운_곰 2020.10.18 2094
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED