bool script_state_save_single(int script_idx,bool checkpoint,char *err_str) { int n,count,prop_name_len,prop_value_len; char prop_name[256]; char *prop_value; script_type *script; JSPropertyNameArrayRef js_names; JSStringRef js_prop_name,js_prop_json; JSValueRef js_prop_value; if (script_idx==-1) return(TRUE); // send save state event scripts_post_event(script_idx,-1,sd_event_state,(checkpoint?sd_event_state_save_checkpoint:sd_event_state_save),0,err_str); // get the script script=js.script_list.scripts[script_idx]; // run through the properities js_names=JSObjectCopyPropertyNames(script->cx,script->global_obj); count=JSPropertyNameArrayGetCount(js_names); for (n=0;n!=count;n++) { // get the property name and value js_prop_name=JSPropertyNameArrayGetNameAtIndex(js_names,n); js_prop_value=JSObjectGetProperty(script->cx,script->global_obj,js_prop_name,NULL); // skip all properties that are functions if (js_prop_value!=NULL) { if (JSValueIsObject(script->cx,js_prop_value)) { if (JSObjectIsFunction(script->cx,(JSObjectRef)js_prop_value)) continue; } } // skip all API objects or DIM3 defines JSStringGetUTF8CString(js_prop_name,prop_name,256); prop_name[255]=0x0; if (script_is_prop_global_object(prop_name)) continue; if (script_is_prop_define(prop_name)) continue; // process the property with JSON js_prop_json=JSValueCreateJSONString(script->cx,js_prop_value,0,NULL); if (js_prop_json==NULL) continue; prop_value_len=JSStringGetMaximumUTF8CStringSize(js_prop_json); prop_value=(char*)malloc(prop_value_len); if (prop_value==NULL) { strcpy(err_str,"Out of Memory"); JSStringRelease(js_prop_json); return(FALSE); } prop_value_len=JSStringGetUTF8CString(js_prop_json,prop_value,prop_value_len); JSStringRelease(js_prop_json); // save property, we have to write a length // with each of these because they can be of any size prop_name_len=strlen(prop_name)+1; game_file_add_chunk(&prop_name_len,1,sizeof(int)); game_file_add_chunk(prop_name,1,prop_name_len); game_file_add_chunk(&prop_value_len,1,sizeof(int)); game_file_add_chunk(prop_value,1,prop_value_len); // free the property value JSON string free(prop_value); } JSPropertyNameArrayRelease(js_names); // end each block with a 0 prop name length prop_name_len=0; game_file_add_chunk(&prop_name_len,1,sizeof(int)); return(TRUE); }
bool game_file_save(char *err_str) { int tick; char path[1024],file_name[256]; bool ok; file_save_header head; progress_initialize("Saving"); progress_draw(5); // get saved data file names tick=game_time_get(); game_file_create_name(tick,file_name); // save screen file_paths_documents(&setup.file_path_setup,path,"Saved Games",file_name,"png"); view_capture_draw(path); // start chunks game_file_sz=0; game_file_data=malloc(32); // header head.tick=tick; strcpy(head.version,dim3_version); strcpy(head.map_name,map.info.name); game_file_add_chunk(&head,1,sizeof(file_save_header)); // send scripts save event // to backup globals progress_draw(10); script_state_save(); // view & server objects progress_draw(20); game_file_add_chunk(&view.time,1,sizeof(view_time_type)); game_file_add_chunk(&view.fps,1,sizeof(view_fps_type)); game_file_add_chunk(&camera,1,sizeof(camera_type)); game_file_add_chunk(&server.time,1,sizeof(server_time_type)); game_file_add_chunk(&server.player_obj_uid,1,sizeof(int)); game_file_add_chunk(&server.skill,1,sizeof(int)); game_file_add_chunk(&server.uid,1,sizeof(server_uid_type)); game_file_add_chunk(&server.count,1,sizeof(server_count_type)); progress_draw(30); game_file_add_chunk(server.objs,server.count.obj,sizeof(obj_type)); game_file_add_chunk(server.weapons,server.count.weapon,sizeof(weapon_type)); game_file_add_chunk(server.proj_setups,server.count.proj_setup,sizeof(proj_setup_type)); progress_draw(40); game_file_add_chunk(server.projs,server.count.proj,sizeof(proj_type)); game_file_add_chunk(server.effects,server.count.effect,sizeof(effect_type)); game_file_add_chunk(server.decals,server.count.decal,sizeof(decal_type)); progress_draw(50); game_file_add_chunk(hud.bitmaps,hud.count.bitmap,sizeof(hud_bitmap_type)); game_file_add_chunk(hud.texts,hud.count.text,sizeof(hud_text_type)); game_file_add_chunk(hud.bars,hud.count.bar,sizeof(hud_bar_type)); game_file_add_chunk(&hud.radar,1,sizeof(hud_radar_type)); // map changes progress_draw(60); game_file_add_chunk(&map.ambient,1,sizeof(map_ambient_type)); game_file_add_chunk(&map.rain,1,sizeof(map_rain_type)); game_file_add_chunk(&map.background,1,sizeof(map_background_type)); game_file_add_chunk(&map.sky,1,sizeof(map_sky_type)); game_file_add_chunk(&map.fog,1,sizeof(map_fog_type)); progress_draw(70); game_file_add_chunk(map.groups,1,sizeof(group_type)*map.ngroup); game_file_add_chunk(map.movements,1,sizeof(movement_type)*map.nmovement); // script objects progress_draw(80); game_file_add_chunk(&js.script_current_uid,1,sizeof(int)); game_file_add_chunk(&js.count,1,sizeof(script_count_type)); game_file_add_chunk(&js.time,1,sizeof(script_time_type)); game_file_add_chunk(js.timers,js.count.timer,sizeof(timer_type)); game_file_add_chunk(js.globals,js.count.global,sizeof(global_type)); // compress and save progress_draw(90); file_paths_documents(&setup.file_path_setup,path,"Saved Games",file_name,"sav"); ok=game_file_compress_save(path,err_str); progress_draw(100); free(game_file_data); // remember last map strcpy(game_file_last_save_name,strrchr(path,'/')); // finished progress_shutdown(); return(ok); }