[웹 어셈블리, 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/

 

 

 

 

 

 

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
34 [javascript] React - Apache에 배포하기 file 졸리운_곰 2026.01.25 444
33 Python으로 GraphQL 서버 구현 file 졸리운_곰 2019.12.17 541
32 처음 만나는 GraphQL file 졸리운_곰 2019.12.17 371
31 웹팩(Webpack) 이란, 웹팩 간단 정리 및 리액트(React) 기본 개발환경 세팅. [2] file 졸리운_곰 2019.11.08 581
30 웹팩(Webpack) 이란, 웹팩 간단 정리 및 리액트(React) 기본 개발환경 세팅. [1] file 졸리운_곰 2019.11.08 411
29 PHP 로 css/js 보호하기 졸리운_곰 2019.11.08 438
28 Three.js를 이용한 WebGL: 기본 file 졸리운_곰 2019.11.08 495
27 underscore.js로 편해지자 졸리운_곰 2018.10.16 545
26 자바스크립트로 각종 값넘기는방법 졸리운_곰 2018.01.24 518
25 form 데이터 주고 받기 file 졸리운_곰 2018.01.24 489
24 Node.js & WebSocket — Simple chat tutorial file 졸리운_곰 2017.12.08 612
23 JavaScript 모듈화 도구, webpack file 졸리운_곰 2017.10.30 537
22 웹팩이란? 졸리운_곰 2017.10.30 531
21 이해하기 쉬운 Webpack 가이드 file 졸리운_곰 2017.10.30 853
20 [jquery] Ajax를 품은 jQuery file 졸리운_곰 2017.04.25 466
19 Create Your First Mobile App with AngularJS and Ionic file 졸리운_곰 2016.11.20 1269
18 Single Page Application using AngularJs Tutorial file 졸리운_곰 2016.11.20 458
17 AngularJS Tutorial - Building a Web App in 5 minutes file 졸리운_곰 2016.11.20 460
16 자바스크립트의 'this' 키워드 이해하기 졸리운_곰 2016.11.17 634
15 jQuery 핵심 - 노드 다루기 졸리운_곰 2016.11.17 774
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED