From 1b3474fe91151b1b733f4f4e4171b5d2a944afe8 Mon Sep 17 00:00:00 2001 From: Luke Van Epen Date: Fri, 4 Apr 2025 12:45:38 +1100 Subject: [PATCH 01/12] refactor: Save/load to json part 2 (#642) --- ChapterMaster.yyp | 3 +- objects/obj_controller/Create_0.gml | 295 +++++--- objects/obj_en_fleet/Create_0.gml | 78 ++ objects/obj_ini/Create_0.gml | 179 ++++- objects/obj_p_fleet/Create_0.gml | 78 ++ objects/obj_saveload/Alarm_0.gml | 52 +- objects/obj_saveload/Create_0.gml | 15 +- objects/obj_saveload/Step_0.gml | 8 +- objects/obj_star/Create_0.gml | 135 ++++ .../scr_array_functions.gml | 24 + .../scr_company_order/scr_company_order.gml | 2 +- .../scr_general_variable_functions.gml | 4 + .../scr_general_variable_functions.yy | 13 + scripts/scr_load/scr_load.gml | 675 +++-------------- .../scr_marine_struct/scr_marine_struct.gml | 8 +- scripts/scr_save/scr_save.gml | 697 +++--------------- .../scr_save_controller.gml | 27 +- .../scr_specialist_point_handler.gml | 2 +- scripts/scr_squads/scr_squads.gml | 13 +- 19 files changed, 969 insertions(+), 1339 deletions(-) create mode 100644 scripts/scr_general_variable_functions/scr_general_variable_functions.gml create mode 100644 scripts/scr_general_variable_functions/scr_general_variable_functions.yy diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 714beea7ae..fce1f95ed2 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -495,7 +495,7 @@ "isEcma":false, "LibraryEmitters":[], "MetaData":{ - "IDEVersion":"2024.1300.0.781", + "IDEVersion":"2024.1300.0.785", }, "name":"ChapterMaster", "resources":[ @@ -736,6 +736,7 @@ {"id":{"name":"scr_fleet_functions","path":"scripts/scr_fleet_functions/scr_fleet_functions.yy",},}, {"id":{"name":"scr_forge_world_functions","path":"scripts/scr_forge_world_functions/scr_forge_world_functions.yy",},}, {"id":{"name":"scr_garrison","path":"scripts/scr_garrison/scr_garrison.yy",},}, + {"id":{"name":"scr_general_variable_functions","path":"scripts/scr_general_variable_functions/scr_general_variable_functions.yy",},}, {"id":{"name":"scr_get_diag_integer","path":"scripts/scr_get_diag_integer/scr_get_diag_integer.yy",},}, {"id":{"name":"scr_get_diag_string","path":"scripts/scr_get_diag_string/scr_get_diag_string.yy",},}, {"id":{"name":"scr_get_item_names","path":"scripts/scr_get_item_names/scr_get_item_names.yy",},}, diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index d5fd000869..bbfa51dfbb 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -72,6 +72,8 @@ The Machine God watches over you. */ +show_debug_message("Creating Controller"); +log_message("Creating Controller"); marine_surface = surface_create(600, 600); scr_colors_initialize(); is_test_map=false; @@ -1344,6 +1346,179 @@ try{ catch(_exception){ global.star_name_colors[1] = make_color_rgb(col_r[1],col_g[1],col_b[1]); } + +get_command_slots_data = function(){ + var _command_slots_data = [ + { + search_params: {}, + role_group_params: { + group: "captain_candidates", + location: "", + opposite: false + }, + purpose: $"{int_to_roman(managing)} Company Captain Candidates", + purpose_code: "captain_promote", + button_text: "New Captain Required", + unit_check: "captain" + }, + { + search_params: { + stat: [["weapon_skill", 44, "more"]], + companies: managing + }, + role_group_params: { + group: [SPECIALISTS_STANDARD, true, true], + location: "", + opposite: true + }, + purpose: $"{int_to_roman(managing)} Company Champion Candidates", + purpose_code: "champion_promote", + button_text: "Champion Required", + unit_check: "champion" + }, + { + search_params: { + companies: managing + }, + role_group_params: { + group: [SPECIALISTS_STANDARD, true, true], + location: "", + opposite: true + }, + purpose: $"{int_to_roman(managing)} Company Ancient Candidates", + purpose_code: "ancient_promote", + button_text: "Ancient Required", + unit_check: "ancient" + }, + { + search_params: { + companies: [managing, 0] + }, + role_group_params: { + group: [SPECIALISTS_CHAPLAINS, false, false], + location: "", + opposite: false + }, + purpose: $"{int_to_roman(managing)} Company Chaplain Candidates", + purpose_code: "chaplain_promote", + button_text: "Chaplain Required", + unit_check: "chaplain" + }, + { + search_params: { + companies: [managing, 0] + }, + role_group_params: { + group: [SPECIALISTS_APOTHECARIES, false, false], + location: "", + opposite: false + }, + purpose: $"{int_to_roman(managing)} Company Apothecary Candidates", + purpose_code: "apothecary_promote", + button_text: "Apothecary Required", + unit_check: "apothecary" + }, + { + search_params: { + companies: [managing, 0] + }, + role_group_params: { + group: [SPECIALISTS_TECHS, false, false], + location: "", + opposite: false + }, + purpose: $"{int_to_roman(managing)} Company Tech Marine Candidates", + purpose_code: "tech_marine_promote", + button_text: "Tech Marine Required", + unit_check: "tech_marine" + }, + { + search_params: { + companies: [managing, 0] + }, + role_group_params: { + group: [SPECIALISTS_LIBRARIANS, false, false], + location: "", + opposite: false + }, + purpose: $"{int_to_roman(managing)} Company Librarian Candidates", + purpose_code: "librarian_promote", + button_text: "Librarian Required", + unit_check: "lib" + } + ]; + + return _command_slots_data; +} + +command_slots_count=array_length(get_command_slots_data()); + +#region save/load serialization + +/// Called from save function to take all object variables and convert them to a json savable format and return it +serialize = function(){ + var object_controller = self; + + var save_data = { + obj: object_get_name(object_index), + x, + y, + chaos_gods, + master_of_forge, + stc_research, + production_research, + player_forge_data, + end_turn_insights, + recruit_data, + marines, + loyalty, + spec_train_data + } + var excluded_from_save = ["temp", "serialize", "deserialize", "build_chaos_gods", "company_data","menu_buttons", + "location_viewer", "production_research_pathways", "specialist_point_handler", "spec_train_data"] + + /// Check all object variable values types and save the simple ones dynamically. + /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. + /// non-simple types are structs, functions, methods + /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. + var all_names = struct_get_names(object_controller); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(excluded_from_save, var_name)){ + continue; + } + if(struct_exists(save_data, var_name)){ + continue; //already added above + } + if(string_starts_with(var_name, "restart_")){ + continue; + } + if(is_basic_variable(object_controller[$var_name])){ + variable_struct_set(save_data, var_name, object_controller[$var_name]); + } + if(is_array(object_controller[$var_name])){ + var _check_arr = object_controller[$var_name]; + var _ok_array = is_basic_array(_check_arr, 2); + if(!_ok_array){ + log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_controller"); + } else { + variable_struct_set(save_data, var_name, object_controller[$var_name]); + } + } + if(is_struct(object_controller[$var_name])){ + if(!struct_exists(save_data, var_name)){ + log_warning($"obj_ini.serialze() - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + } + } + } + return save_data; +} + +// Deserialization is done within scr_load +#endregion + + // ** Loads the game ** if (global.load>0){ load_game=global.load; @@ -1361,6 +1536,18 @@ if (global.load>0){ exit; } +///! ************************************************************ */ +///! ************************************************************ */ +///! ************************************************************ */ +///! NOTHING BEYOND THIS POINT WILL BE SET AFTER A LOAD FROM SAVE */ +///! ************************************************************ */ +///! ************************************************************ */ +///! ************************************************************ */ +///! ************************************************************ */ + + + + var xx,yy,me,dist,go,planet; global.custom=1; @@ -1784,112 +1971,10 @@ if (welcome_pages>=5){ } } remov=string_length(string(temp[65])+string(temp[66])+string(temp[67])+string(temp[68])+string(temp[69]))+1; -action_set_alarm(2, 0); instance_create(0,0,obj_tooltip ); -get_command_slots_data = function(){ - var _command_slots_data = [ - { - search_params: {}, - role_group_params: { - group: "captain_candidates", - location: "", - opposite: false - }, - purpose: $"{int_to_roman(managing)} Company Captain Candidates", - purpose_code: "captain_promote", - button_text: "New Captain Required", - unit_check: "captain" - }, - { - search_params: { - stat: [["weapon_skill", 44, "more"]], - companies: managing - }, - role_group_params: { - group: [SPECIALISTS_STANDARD, true, true], - location: "", - opposite: true - }, - purpose: $"{int_to_roman(managing)} Company Champion Candidates", - purpose_code: "champion_promote", - button_text: "Champion Required", - unit_check: "champion" - }, - { - search_params: { - companies: managing - }, - role_group_params: { - group: [SPECIALISTS_STANDARD, true, true], - location: "", - opposite: true - }, - purpose: $"{int_to_roman(managing)} Company Ancient Candidates", - purpose_code: "ancient_promote", - button_text: "Ancient Required", - unit_check: "ancient" - }, - { - search_params: { - companies: [managing, 0] - }, - role_group_params: { - group: [SPECIALISTS_CHAPLAINS, false, false], - location: "", - opposite: false - }, - purpose: $"{int_to_roman(managing)} Company Chaplain Candidates", - purpose_code: "chaplain_promote", - button_text: "Chaplain Required", - unit_check: "chaplain" - }, - { - search_params: { - companies: [managing, 0] - }, - role_group_params: { - group: [SPECIALISTS_APOTHECARIES, false, false], - location: "", - opposite: false - }, - purpose: $"{int_to_roman(managing)} Company Apothecary Candidates", - purpose_code: "apothecary_promote", - button_text: "Apothecary Required", - unit_check: "apothecary" - }, - { - search_params: { - companies: [managing, 0] - }, - role_group_params: { - group: [SPECIALISTS_TECHS, false, false], - location: "", - opposite: false - }, - purpose: $"{int_to_roman(managing)} Company Tech Marine Candidates", - purpose_code: "tech_marine_promote", - button_text: "Tech Marine Required", - unit_check: "tech_marine" - }, - { - search_params: { - companies: [managing, 0] - }, - role_group_params: { - group: [SPECIALISTS_LIBRARIANS, false, false], - location: "", - opposite: false - }, - purpose: $"{int_to_roman(managing)} Company Librarian Candidates", - purpose_code: "librarian_promote", - button_text: "Librarian Required", - unit_check: "lib" - } - ]; - - return _command_slots_data; -} +action_set_alarm(2, 0); -command_slots_count=array_length(get_command_slots_data()); + +//**! DO NOT PUT THINGS AT THE BOTTOM OF THIS FILE IF YOU NEED THEM TO WORK AFTER LOADING FROM A SAVE, SEE LINE 1550 -ish */ \ No newline at end of file diff --git a/objects/obj_en_fleet/Create_0.gml b/objects/obj_en_fleet/Create_0.gml index 8a2abc8731..8f5412668c 100644 --- a/objects/obj_en_fleet/Create_0.gml +++ b/objects/obj_en_fleet/Create_0.gml @@ -69,3 +69,81 @@ escort_health=100; alarm[8]=1; +#region save/load serialization + +/// Called from save function to take all object variables and convert them to a json savable format and return it +serialize = function(){ + var object_fleet = self; + + var save_data = { + obj: object_get_name(object_index), + x, + y, + } + + var excluded_from_save = ["temp", "serialize", "deserialize", "cargo_data"] + + /// Check all object variable values types and save the simple ones dynamically. + /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. + /// non-simple types are structs, functions, methods + /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. + var all_names = struct_get_names(object_fleet); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(excluded_from_save, var_name)){ + continue; + } + if(struct_exists(save_data, var_name)){ + continue; //already added above + } + if(is_basic_variable(object_fleet[$var_name])){ + variable_struct_set(save_data, var_name, object_fleet[$var_name]); + } + if(is_array(object_fleet[$var_name])){ + var _check_arr = object_fleet[$var_name]; + var _ok_array = is_basic_array(_check_arr, 2); + if(!_ok_array){ + log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_en_fleet"); + } else { + variable_struct_set(save_data, var_name, object_fleet[$var_name]); + } + } + if(is_struct(object_fleet[$var_name])){ + if(!struct_exists(save_data, var_name)){ + log_warning($"WARNING: obj_ini.serialze() - obj_en_fleet - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + } + } + } + + + return save_data; +} +deserialize = function(save_data){ + var exclusions = ["id"]; // skip automatic setting of certain vars, handle explicitly later + + // Automatic var setting + var all_names = struct_get_names(save_data); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(exclusions, var_name)){ + continue; + } + var loaded_value = struct_get(save_data, var_name); + // show_debug_message($"en_fleet {en_fleet_instance.id} - var: {var_name} - val: {loaded_value}"); + try { + variable_struct_set(self, var_name, loaded_value); + } catch (e){ + show_debug_message(e); + } + } + + if(save_data.orbiting != 0){ + var nearest_star = instance_nearest(x, y, obj_star); + orbiting = nearest_star; + // show_debug_message($"p_fleet id {id} deserialized: {self}"); + } +} + +#endregion \ No newline at end of file diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 02b38e14d8..4fd8f816e0 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -31,6 +31,7 @@ penitent_current=0; penitent_end=0; man_size=0; home_planet = 2; +artifact_struct = array_create(200); // Equipment- maybe the bikes should go here or something? yes they should i=-1; @@ -103,15 +104,185 @@ gene_slaves = []; if (obj_creation.custom=0) then scr_initialize_standard(); }*/ +adv = []; +dis = []; + + if (instance_exists(obj_creation)) then custom=obj_creation.custom; if (global.load=0) then scr_initialize_custom(); +#region save/load serialization + +/// Called from save function to take all object variables and convert them to a json savable format and return it +serialize = function(){ + var object_ini = self; + + var marines = array_create(0); + for(var coy = 0; coy <=10; coy++){ + for(var mar = 0; mar <=500; mar++){ + var marine_json; + if(obj_ini.name[coy][mar] != ""){ + marine_json = jsonify_marine_struct(coy, mar, false); + array_push(marines, marine_json); + } else if(mar > 0){ + break; + } + } + } + var squads = []; + if (array_length(object_ini.squads)> 0){ + for (var i = 0;i < array_length(object_ini.squads);i++){ + array_push(squads, object_ini.squads[i].jsonify(false)); + } + } + + var artifact_struct_trimmed = []; + for(var i = 0; i < array_length(artifact_struct); i++){ + if(artifact_struct[i].name != ""){ + array_push(artifact_struct_trimmed, artifact_struct[i]); + } + } + + + var save_data = { + obj: object_get_name(object_index), + x, + y, + custom_advisors, + full_liveries: full_liveries, + complex_livery_data: complex_livery_data, + squad_types: squad_types, + artifact_struct: artifact_struct_trimmed, + marine_structs: marines, + squad_structs: squads, + // marines, + // squads + } + + if(struct_exists(object_ini, "last_ship")){ + save_data.last_ship = object_ini.last_ship; + } + + var excluded_from_save = ["temp", "serialize", "deserialize", "load_default_gear", "role_spawn_buffs", "TTRPG", "squads", "squad_types", "marines", "last_ship"] + + /// Check all object variable values types and save the simple ones dynamically. + /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. + /// non-simple types are structs, functions, methods + /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. + var all_names = struct_get_names(object_ini); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(excluded_from_save, var_name)){ + continue; + } + if(struct_exists(save_data, var_name)){ + continue; //already added above + } + if(is_basic_variable(object_ini[$var_name])){ + variable_struct_set(save_data, var_name, object_ini[$var_name]); + } + if(is_array(object_ini[$var_name])){ + var _check_arr = object_ini[$var_name]; + var _ok_array = is_basic_array(_check_arr, 2); + if(!_ok_array){ + log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_ini"); + } else { + variable_struct_set(save_data, var_name, object_ini[$var_name]); + } + } + if(is_struct(object_ini[$var_name])){ + if(!struct_exists(save_data, var_name)){ + log_warning($"WARNING: obj_ini.serialze() - obj_ini - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + } + } + } + return save_data; +} +deserialize = function(save_data){ + var exclusions = ["complex_livery_data", "full_liveries", "squad_types", "marine_structs", "squad_structs"]; // skip automatic setting of certain vars, handle explicitly later + // Automatic var setting + var all_names = struct_get_names(save_data); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(exclusions, var_name)){ + continue; + } + + var loaded_value = struct_get(save_data, var_name); + // show_debug_message($"obj_ini var: {var_name} - val: {loaded_value}"); + try { + variable_struct_set(obj_ini, var_name, loaded_value); + } catch (e){ + show_debug_message(e); + } + } + + // Set explicit vars here + var livery_picker = new ColourItem(0,0); + livery_picker.scr_unit_draw_data(); + if(struct_exists(save_data, "full_liveries")){ + variable_struct_set(obj_ini, "full_liveries", save_data.full_liveries) + } else { + variable_struct_set(obj_ini, "full_liveries", array_create(21,DeepCloneStruct(livery_picker.map_colour))); + } + + if(struct_exists(save_data, "complex_livery_data")){ + variable_struct_set(obj_ini, "complex_livery_data", save_data.complex_livery_data); + } + if(struct_exists(save_data, "squad_types")){ + variable_struct_set(obj_ini, "squad_types", save_data.squad_types); + } + + if(struct_exists(save_data, "marine_structs")){ + var marines_encoded_arr = save_data.marine_structs; + var _m_ar_len = array_length(marines_encoded_arr); + for(var m = 0; m < _m_ar_len; m++){ + var marine_json = marines_encoded_arr[m]; + var coy = marine_json.company; + var mar = marine_json.marine_number; + load_marine_struct(coy, mar, marine_json); + } + for(var coy = 0; coy < 11; coy++){ + var mar_start = array_length(obj_ini.TTRPG[coy]); + for(var mar = mar_start; mar < 501; mar++){ + obj_ini.TTRPG[coy][mar] = new TTRPG_stats("chapter",coy, mar, "blank"); + } + } + } + + if(struct_exists(save_data, "squad_structs")){ + obj_ini.squads = []; + var squad_fetch = save_data.squad_structs; + for (i=0;i0) then txt="Praise be to the Emperor"; with(obj_controller){ + // show_debug_message($"load section 5"); scr_load(5,global.load); - // **sets up starting forge_points - location_viewer = new UnitQuickFindPanel(); - specialist_point_handler.calculate_research_points(); - - //** sets up marine_by_location view - with(obj_controller){ - global.star_name_colors[1] = make_color_rgb(body_colour_replace[0],body_colour_replace[1],body_colour_replace[2]); - sector_imperial_fleet_strength(); - } } - trickle=50; + trickle=2; if (instance_exists(obj_cuicons)){ obj_cuicons.alarm[1]=30; } @@ -91,9 +81,10 @@ if (load_part == 5) { } with (obj_controller) { + // show_debug_message($"load section 4"); scr_load(4, global.load); } - trickle = 10; + trickle = 2; load_part = 6; } @@ -103,9 +94,10 @@ if (load_part == 4) { txt = "Donning Power Armour"; } with (obj_controller) { + // show_debug_message($"load section 3"); scr_load(3, global.load); } - trickle = 40; + trickle = 2; load_part = 5; } @@ -115,9 +107,10 @@ if (load_part == 3) { txt = "Rousing the Machine Spirit"; } with (obj_controller) { + // show_debug_message($"load section 2"); scr_load(2, global.load); } - trickle = 10; + trickle = 2; load_part = 4; } @@ -127,16 +120,17 @@ if (load_part == 2) { txt = "Turtle Waxing Scalp"; } with (obj_controller) { + // show_debug_message($"load section 1"); scr_load(1, global.load); } - trickle = 10; + trickle = 2; load_part = 3; } if (load_part == 1) { - if (file_exists("save" + string(global.load) + ".ini")) { + if (file_exists($"save{global.load}.json")) { load_part += 1; - trickle = 10; + trickle = 2; txt = "Preparing"; } } diff --git a/objects/obj_saveload/Create_0.gml b/objects/obj_saveload/Create_0.gml index 55b6d46ea5..7f8aa458a1 100644 --- a/objects/obj_saveload/Create_0.gml +++ b/objects/obj_saveload/Create_0.gml @@ -1,10 +1,18 @@ scr_image("loading",-50,0,0,0,0); +GameSave = {}; +GameSave.Stars = []; +GameSave.PlayerFleet = []; +GameSave.EnemyFleet = []; +GameSave.Ini = {}; +GameSave.Controller = {}; +GameSave.EventLog = []; menu=0;// 1 : save, 2: load save_part=0; load_part=0; save_number=0; +/// number of frames between load sections to draw the progress bar trickle=0; txt=""; hide=0; @@ -45,12 +53,11 @@ repeat(201){i+=1; } i=0; repeat(100){i+=1; - if (file_exists("save"+string(i)+".ini")){ + if (file_exists($"save{i}.json")){ saves+=1;save[saves]=i; } - if (!file_exists("save"+string(i)+".ini")) and (i>0) and (max_ini=0) then max_ini=i; - if (file_exists("save"+string(i+1)+".ini")) and (max_ini>0) then max_ini=0; -} + if (!file_exists($"save{i}.json")) and (i>0) and (max_ini=0) then max_ini=i; + if (file_exists($"save{i+1}.json")) and (max_ini>0) then max_ini=0;} first_open=saves+1; diff --git a/objects/obj_saveload/Step_0.gml b/objects/obj_saveload/Step_0.gml index cb0b22e0a1..7879a85777 100644 --- a/objects/obj_saveload/Step_0.gml +++ b/objects/obj_saveload/Step_0.gml @@ -6,11 +6,13 @@ if (reset>=50){ } if (trickle>-1){ - + var save_parts = 6; + + trickle-=1; - if (trickle>0) then bar+=1; + if (trickle>0) then bar+= min(100, round(100/save_parts)); if (trickle=0) then alarm[0]=1; - if (bar+1>=100) and (bar!=100){trickle=-1;bar=100;alarm[0]=-1;alarm[1]=20;} + if (bar>=100){trickle=-1;bar=100;alarm[0]=-1;alarm[1]=5;} } diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index af92514adc..1ee766aa0b 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -109,3 +109,138 @@ global.star_name_colors = [ #AD5272, //why 12 is skipped in general, we will never know #80FF00 // Sleepy robots ] + + +#region save/load serialization + +/// Called from save function to take all object variables and convert them to a json savable format and return it +serialize = function(){ + var object_star = self; + + var planet_data = []; + + for(var p = 1; p <= object_star.planets; p++){ + planet_data[p] = { + dispo: object_star.dispo[p], + planet: object_star.planet[p], + }; + var var_names = variable_struct_get_names(object_star); + for(var n = 0; n < array_length(var_names); n++){ + var var_name = var_names[n]; + if(string_starts_with(var_name, "p_")){ + var val = object_star[$var_name][p]; + variable_struct_set(planet_data[p], var_name, val); + } + } + } + + + var save_data = { + obj: object_get_name(object_index), + x, + y, + present_fleet: base64_encode(json_stringify(object_star.present_fleet)), + planet_data: planet_data, + } + if(struct_exists(object_star, "system_garrison")){ + save_data.system_garrison = base64_encode(json_stringify(object_star.system_garrison)); + } + if(struct_exists(object_star, "system_sabatours")){ + save_data.system_sabatours = base64_encode(json_stringify(object_star.system_sabatours)); + } + + + var excluded_from_save = ["temp", "serialize", "deserialize", "arraysum"] + + /// Check all object variable values types and save the simple ones dynamically. + /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. + /// non-simple types are structs, functions, methods + /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. + var all_names = struct_get_names(object_star); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(excluded_from_save, var_name)){ + continue; + } + if(string_starts_with(var_name, "p_")){ + continue; //handled in planet_data above + } + if(struct_exists(save_data, var_name)){ + continue; //already added above + } + if(is_basic_variable(object_star[$var_name])){ + variable_struct_set(save_data, var_name, object_star[$var_name]); + } + if(is_array(object_star[$var_name])){ + var _check_arr = object_star[$var_name]; + var _ok_array = true; + var _ok_array = is_basic_array(_check_arr, 2); + if(!_ok_array){ + log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - object_star"); + } else { + variable_struct_set(save_data, var_name, object_star[$var_name]); + } + } + if(is_struct(object_star[$var_name])){ + if(!struct_exists(save_data, var_name)){ + log_warning($"WARNING: obj_ini.serialze() - obj_star - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + } + } + } + + return save_data; +} + +function deserialize(save_data){ + var exclusions = ["id", "present_fleet", "planet_data"]; // skip automatic setting of certain vars, handle explicitly later + + // Automatic var setting + var all_names = struct_get_names(save_data); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(exclusions, var_name)){ + continue; + } + var loaded_value = struct_get(save_data, var_name); + variable_struct_set(self, var_name, loaded_value); + } + + // Set explicit vars here + if(struct_exists(save_data, "present_fleet")){ + var encoded_fleet = save_data.present_fleet; + variable_struct_set(self, "present_fleet", json_parse(base64_decode(encoded_fleet))); + } + + if(struct_exists(save_data, "planet_data")){ + var planet_arr = save_data.planet_data; + var _len = array_length(planet_arr); + for(var p = 1; p < _len; p++){ + var planet = planet_arr[p]; + var var_names = struct_get_names(planet); + for(var v = 0; v < array_length(var_names); v++){ + var var_name = var_names[v]; + var val = planet[$var_name]; + // var_name = "p_type" + // planet = {"p_type":"hive"}; + // val = planet[$var_name] = "hive" + + self[$var_name][p] = val; + // variable_struct_set(self, var_name, planet[$var_name]); + } + } + } + + if(struct_exists(save_data, "system_sabatours")){ + var encoded_sabatours = save_data.system_sabatours; + variable_struct_set(self, "system_sabatours", json_parse(base64_decode(encoded_sabatours))); + } + if(struct_exists(save_data, "system_garrison")){ + var encoded_garrison = save_data.system_garrison; + variable_struct_set(self, "system_garrison", json_parse(base64_decode(encoded_garrison))); + } + +} + +#endregion \ No newline at end of file diff --git a/scripts/scr_array_functions/scr_array_functions.gml b/scripts/scr_array_functions/scr_array_functions.gml index dda5d22fa6..6afd8656d8 100644 --- a/scripts/scr_array_functions/scr_array_functions.gml +++ b/scripts/scr_array_functions/scr_array_functions.gml @@ -189,3 +189,27 @@ function smart_delimeter_sign(_array_or_length, _loop_iteration, _dot_end = true return _delimeter; } + +/// @description Checks whether an array is "simple," meaning it does not exceed a specified depth and contains only simple variables. Recursively evaluates nested arrays. +/// @param {array} _array - The array to check. +/// @param {real} _max_depth - The maximum allowed depth for the array. +/// @param {real} _current_depth (DON'T PASS ANYTHING) The current recursion depth, used internally. +/// @returns {bool} +function is_basic_array(_array, _max_depth = 1, _current_depth = 1) { + if (_current_depth > _max_depth) { + return false; + } + + for (var i = 0, _len = array_length(_array); i < _len; i++) { + var _var = _array[i]; + if (is_array(_var)) { + if (!is_basic_array(_var, _max_depth, _current_depth + 1)) { + return false; + } + } else if (!is_basic_variable(_var)) { + return false; + } + } + + return true; +} diff --git a/scripts/scr_company_order/scr_company_order.gml b/scripts/scr_company_order/scr_company_order.gml index bd31adabaa..c2ea440780 100644 --- a/scripts/scr_company_order/scr_company_order.gml +++ b/scripts/scr_company_order/scr_company_order.gml @@ -47,7 +47,7 @@ function sort_all_companies(){ } } function scr_company_order(company) { - try_and_report_loop("company order", function(company){ + try_and_report_loop($"company order {company}", function(company){ // company : company number // This sorts and crunches the marine variables for the company diff --git a/scripts/scr_general_variable_functions/scr_general_variable_functions.gml b/scripts/scr_general_variable_functions/scr_general_variable_functions.gml new file mode 100644 index 0000000000..def81cb8cc --- /dev/null +++ b/scripts/scr_general_variable_functions/scr_general_variable_functions.gml @@ -0,0 +1,4 @@ +/// @description Checks if a variable is a simple data type (number, string, or boolean). +function is_basic_variable(_variable) { + return is_numeric(_variable) || is_string(_variable) || is_bool(_variable); +} diff --git a/scripts/scr_general_variable_functions/scr_general_variable_functions.yy b/scripts/scr_general_variable_functions/scr_general_variable_functions.yy new file mode 100644 index 0000000000..f968da3922 --- /dev/null +++ b/scripts/scr_general_variable_functions/scr_general_variable_functions.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"scr_general_variable_functions", + "isCompatibility":false, + "isDnD":false, + "name":"scr_general_variable_functions", + "parent":{ + "name":"Scripts", + "path":"folders/Scripts.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/scr_load/scr_load.gml b/scripts/scr_load/scr_load.gml index 9ad49b32bb..0bf325fe2e 100644 --- a/scripts/scr_load/scr_load.gml +++ b/scripts/scr_load/scr_load.gml @@ -1,615 +1,148 @@ -function return_json_from_ini(ini_area,ini_code, default_val=[]){ - var ini_fetch = ini_read_string(ini_area,ini_code,""); - if (ini_fetch!=""){ - return json_parse(base64_decode(ini_fetch)); - } else { - return default_val; - } -} +function load_marine_struct(company, marine, struct){ -function load_marine_struct(company, marine){ - var marStruct = ini_read_string("Mar","Struct"+string(company)+"."+string(marine),""); - if (marStruct != ""){ - marStruct = json_parse(base64_decode(marStruct)); - obj_ini.TTRPG[company, marine] = new TTRPG_stats("chapter", company, marine, "blank"); - obj_ini.TTRPG[company, marine].load_json_data(marStruct); - delete marStruct; - } else { - obj_ini.TTRPG[company, marine] = new TTRPG_stats("chapter", company, marine,"blank"); - } + obj_ini.TTRPG[company, marine] = new TTRPG_stats("chapter", company, marine, "blank"); + obj_ini.TTRPG[company, marine].load_json_data(struct); + }; function scr_load(save_part, save_id) { - var unit; - var rang=0,stars=0,pfleets=0,efleets=0; - - - - if (save_part=1) or (save_part=0){ - scr_load_controller(save_id); + var filename = $"save{save_id}.json"; + if(file_exists(filename)){ + var _gamesave_buffer = buffer_load(filename); + var _gamesave_string = buffer_read(_gamesave_buffer, buffer_string); + var json_game_save = json_parse(_gamesave_string); } - - if (save_part=2) or (save_part=0){ - log_message("Loading slot "+string(save_id)+" part 2"); - ini_open("tsave.ini"); - - stars=ini_read_real("Save","stars",0); - - // Stars - var i=-1; - repeat(stars){i+=1; - var new_star; - new_star=instance_create( - ini_read_real("Star",$"sr{i}x",0), - ini_read_real("Star",$"sr{i}y",0), - obj_star - ); - - new_star.name=ini_read_string("Star",$"sr{i}name",""); - new_star.star=ini_read_string("Star",$"sr{i}star",""); - new_star.planets=ini_read_real("Star",$"sr{i}planets",0); - new_star.owner=ini_read_real("Star",$"sr{i}owner",0); - new_star.x2=ini_read_real("Star",$"sr{i}x2",0); - new_star.y2=ini_read_real("Star",$"sr{i}y2",0); - new_star.old_x=ini_read_real("Star",$"sr{i}ox",0); - new_star.old_y=ini_read_real("Star",$"sr{i}oy",0); - new_star.warp_lanes = return_json_from_ini("Star",$"sr{i}warp_lanes",[]); - - new_star.vision=ini_read_real("Star",$"sr{i}vision",1); - new_star.storm=ini_read_real("Star",$"sr{i}storm",0); - new_star.trader=ini_read_real("Star",$"sr{i}trader",0); - new_star.craftworld=ini_read_real("Star",$"sr{i}craftworld",0); - new_star.space_hulk=ini_read_real("Star",$"sr{i}spacehulk",0); - if (new_star.space_hulk=1) then new_star.sprite_index=spr_star_hulk; - new_star.present_fleet=ini_read_string("Star",$"sr{i}present_fleets",""); - if (new_star.present_fleet!=""){ - new_star.present_fleet = json_parse(base64_decode(new_star.present_fleet)); - } else { - new_star.present_fleet = array_create(30, 0); - } - - var g=0; - repeat(4){g+=1; - if (new_star.planets>=g){ - new_star.planet[g]=ini_read_real("Star",$"sr{i}plan"+string(g),0); - new_star.dispo[g]=ini_read_real("Star",$"sr{i}dispo"+string(g),-10); - new_star.p_type[g]=ini_read_string("Star",$"sr{i}type"+string(g),""); - new_star.p_feature[g] = []; - var p_features = ini_read_string("Star",$"sr{i}feat"+string(g),""); - if (p_features != ""){ - var p_features = json_parse(base64_decode(p_features)); - for (var feat = 0;feat < array_length(p_features);feat++){ - var new_feat = new NewPlanetFeature(p_features[feat].f_type); - new_feat.load_json_data(p_features[feat]); - array_push(new_star.p_feature[g], new_feat); - } - } - new_star.p_owner[g]=ini_read_real("Star",$"sr{i}own"+string(g),0); - new_star.p_first[g]=ini_read_real("Star",$"sr{i}fir"+string(g),0); - new_star.p_population[g]=ini_read_real("Star",$"sr{i}popul"+string(g),0); - new_star.p_max_population[g]=ini_read_real("Star",$"sr{i}maxpop"+string(g),0); - new_star.p_large[g]=ini_read_real("Star",$"sr{i}large"+string(g),0); - new_star.p_pop[g]=ini_read_string("Star",$"sr{i}pop"+string(g),""); - new_star.p_guardsmen[g]=ini_read_real("Star",$"sr{i}guard"+string(g),0); - new_star.p_pdf[g]=ini_read_real("Star",$"sr{i}pdf"+string(g),0); - new_star.p_fortified[g]=ini_read_real("Star",$"sr{i}forti"+string(g),0); - new_star.p_station[g]=ini_read_real("Star",$"sr{i}stat"+string(g),0); - - new_star.p_player[g]=ini_read_real("Star",$"sr{i}play"+string(g),0); - new_star.p_lasers[g]=ini_read_real("Star",$"sr{i}p_lasers"+string(g),0); - new_star.p_silo[g]=ini_read_real("Star",$"sr{i}p_silo"+string(g),0); - new_star.p_defenses[g]=ini_read_real("Star",$"sr{i}p_defenses"+string(g),0); - new_star.p_operatives[g]=ini_read_string("Star",$"sr{i}operatives"+string(g),0); - if (new_star.p_operatives[g]!=0){ - new_star.p_operatives[g] = json_parse(base64_decode(new_star.p_operatives[g])) - } - new_star.p_upgrades[g] = []; - var p_upgrades = ini_read_string("Star",$"sr{i}upg"+string(g),""); - if (p_upgrades != ""){ - var p_upgrades = json_parse(base64_decode(p_upgrades)); - for (var feat = 0;feat < array_length(p_upgrades);feat++){ - var new_feat = new NewPlanetFeature(p_upgrades[feat].f_type); - new_feat.load_json_data(p_upgrades[feat]); - array_push(new_star.p_upgrades[g], new_feat); - } - } - - new_star.p_orks[g]=ini_read_real("Star",$"sr{i}or"+string(g),0); - new_star.p_tau[g]=ini_read_real("Star",$"sr{i}ta"+string(g),0); - new_star.p_eldar[g]=ini_read_real("Star",$"sr{i}el"+string(g),0); - new_star.p_traitors[g]=ini_read_real("Star",$"sr{i}tr"+string(g),0); - new_star.p_chaos[g]=ini_read_real("Star",$"sr{i}ch"+string(g),0); - new_star.p_demons[g]=ini_read_real("Star",$"sr{i}de"+string(g),0); - new_star.p_sisters[g]=ini_read_real("Star",$"sr{i}si"+string(g),0); - new_star.p_necrons[g]=ini_read_real("Star",$"sr{i}ne"+string(g),0); - new_star.p_tyranids[g]=ini_read_real("Star",$"sr{i}tyr"+string(g),0); - new_star.p_halp[g]=ini_read_real("Star",$"sr{i}halp"+string(g),0); - - new_star.p_heresy[g]=ini_read_real("Star",$"sr{i}heresy"+string(g),0); - new_star.p_hurssy[g]=ini_read_real("Star",$"sr{i}hurssy"+string(g),0); - new_star.p_hurssy_time[g]=ini_read_real("Star",$"sr{i}hurssy_time"+string(g),0); - new_star.p_heresy_secret[g]=ini_read_real("Star",$"sr{i}heresy_secret"+string(g),0); - new_star.p_influence[g]=ini_read_string("Star",$"sr{i}influence"+string(g),""); - if (new_star.p_influence[g] != ""){ - new_star.p_influence[g]=json_parse(base64_decode(new_star.p_influence[g])); - } else { - new_star.p_influence[g] = array_create(15, 0); - } - new_star.p_raided[g]=ini_read_real("Star",$"sr{i}raided"+string(g),0); - - - for (var p=0;p<8;p++){ - new_star.p_problem[g,p]=ini_read_string("Star",$"sr{i}prob{g}.{p}",""); - new_star.p_timer[g,p]=ini_read_real("Star",$"sr{i}time{g}.{p}",-1); - new_star.p_problem_other_data[g,p]=ini_read_string("Star",$"sr{i}prob_other{g}.{p}",""); - if (new_star.p_problem_other_data[g][p]!=""){ - new_star.p_problem_other_data[g][p] = json_parse(base64_decode(new_star.p_problem_other_data[g][p])); - } else { - new_star.p_problem_other_data[g][p]={}; - } - } - } - } - } - - - // obj_ini - //TODO allow methods to be passed as teh default to return_json_from_ini to optomise load speed - var livery_picker = new ColourItem(0,0); - livery_picker.scr_unit_draw_data(); - obj_ini.full_liveries = return_json_from_ini("Ini", "full_liveries",array_create(21,DeepCloneStruct(livery_picker.map_colour))); - obj_ini.culture_styles = return_json_from_ini("Ini", "styles", []); - obj_ini.custom_advisors = return_json_from_ini("Ini", "custom_advisors",{}); - obj_ini.home_name=ini_read_string("Ini","home_name","Error"); - obj_ini.home_type=ini_read_string("Ini","home_type","Error"); - obj_ini.recruiting_name=ini_read_string("Ini","recruiting_name","Error"); - obj_ini.recruiting_type=ini_read_string("Ini","recruiting_type","Error"); - obj_ini.chapter_name=ini_read_string("Ini","chapter_name","Error"); - obj_ini.fortress_name=ini_read_string("Ini","fortress_name","Error"); - obj_ini.flagship_name=ini_read_string("Ini","flagship_name","Error"); - obj_ini.icon=ini_read_real("Ini","icon",0); - obj_ini.icon_name=ini_read_string("Ini","icon_name","custom1"); - global.icon_name=obj_ini.icon_name; - obj_ini.man_size=ini_read_real("Ini","man_size",0); - // obj_ini.strin=ini_read_string("Ini","strin1",""); - // obj_ini.strin2=ini_read_string("Ini","strin2",""); - obj_ini.psy_powers=ini_read_string("Ini","psy_powers","librarius"); - - - global.chapter_icon_sprite = ini_read_real("Ini", "global_chapter_icon_sprite", spr_icon_chapters); - global.chapter_icon_frame = ini_read_real("Ini", "global_chapter_icon_frame", 0); - global.chapter_icon_path = ini_read_string("Ini", "global_chapter_icon_path", "Error"); - global.chapter_icon_filename = ini_read_real("Ini", "global_chapter_icon_filename", 0); + if(!struct_exists(obj_saveload.GameSave, "Save")){ + obj_saveload.GameSave = json_game_save; + } + if (save_part=1) or (save_part=0){ + log_message("Loading GLOBALS"); + // Globals + var globals = obj_saveload.GameSave.Save; + global.chapter_icon_sprite = spr_icon_chapters; + global.chapter_icon_frame = globals.chapter_icon_frame; + global.chapter_icon_path = globals.chapter_icon_path; + global.chapter_icon_filename = globals.chapter_icon_filename; + global.icon_name=globals.icon_name; + global.chapter_name = globals.chapter_name; + global.custom = globals.custom; if(global.chapter_icon_path != "Error" && global.chapter_icon_path != "") { global.chapter_icon_sprite = scr_image_cache(global.chapter_icon_path, global.chapter_icon_filename); } else { global.chapter_icon_sprite = spr_icon_chapters; } + // global.icon = globals.icon; + - obj_ini.companies=ini_read_real("Ini","companies",10); - obj_ini.company_title = return_json_from_ini("Ini","comp_title",array_create(21,"")); + } - obj_ini.gene_slaves = return_json_from_ini("Ini","gene_slaves",[]); - - obj_ini.complex_livery_data=ini_read_string("Ini","complex_livery",""); - if (obj_ini.complex_livery_data!=""){ - obj_ini.complex_livery_data=json_parse(base64_decode(obj_ini.complex_livery_data)); - } else{ - //TODO centralise and initialisation method for this other reference place is obj_creation create - obj_ini.complex_livery_data = complex_livery_default(); - } - var colour_temp = new ColourItem(0,0); - obj_ini.full_liveries = return_json_from_ini("Ini", "FullLivery",colour_temp.scr_unit_draw_data()); - // - obj_ini.preomnor=ini_read_real("Ini","preomnor",0); - obj_ini.voice=ini_read_real("Ini","voice",0); - obj_ini.doomed=ini_read_real("Ini","doomed",0); - obj_ini.lyman=ini_read_real("Ini","lyman",0); - obj_ini.omophagea=ini_read_real("Ini","omophagea",0); - obj_ini.ossmodula=ini_read_real("Ini","ossmodula",0); - obj_ini.membrane=ini_read_real("Ini","membrane",0); - obj_ini.zygote=ini_read_real("Ini","zygote",0); - obj_ini.betchers=ini_read_real("Ini","betchers",0); - obj_ini.catalepsean=ini_read_real("Ini","catalepsean",0); - obj_ini.secretions=ini_read_real("Ini","secretions",0); - obj_ini.occulobe=ini_read_real("Ini","occulobe",0); - obj_ini.mucranoid=ini_read_real("Ini","mucranoid",0); - // - obj_ini.master_name=ini_read_string("Ini","master_name","Error"); - obj_ini.chief_librarian_name=ini_read_string("Ini","chief_name","Error"); - obj_ini.high_chaplain_name=ini_read_string("Ini","high_name","Error"); - obj_ini.high_apothecary_name=ini_read_string("Ini","high2_name","Error"); - obj_ini.forge_master_name=ini_read_string("Ini","forgey_name","Error"); - obj_ini.lord_admiral_name=ini_read_string("Ini","lord_name","Error"); - obj_ini.previous_forge_masters=ini_read_string("Ini","previous_forge_masters",[]); - if (!is_array(obj_ini.previous_forge_masters)){ - obj_ini.previous_forge_masters=json_parse(base64_decode(obj_ini.previous_forge_masters)); - } - // - // - obj_ini.equipment=return_json_from_ini("Ini",$"equipment", array_create(200,"")) - obj_ini.equipment_type=return_json_from_ini("Ini",$"equipment_type", array_create(200,"")) - obj_ini.equipment_number=return_json_from_ini("Ini",$"equipment_number", array_create(200,"")) - obj_ini.equipment_condition=return_json_from_ini("Ini",$"equipment_condition",array_create(200,"")) - obj_ini.equipment_quality = return_json_from_ini("Ini", $"equipment_quality", array_create(200,"")) + if (save_part=2) or (save_part=0){ + log_message("Loading STARS"); - for (var g=0; g0) then obj_ini.race[coh,mah]=1; - } - - obj_ini.wep1[coh,mah]=ini_read_string("Mar","w1"+string(coh)+"."+string(mah),""); - obj_ini.wep2[coh,mah]=ini_read_string("Mar","w2"+string(coh)+"."+string(mah),""); - obj_ini.armour[coh,mah]=ini_read_string("Mar","ar"+string(coh)+"."+string(mah),""); - obj_ini.gear[coh,mah]=ini_read_string("Mar","ge"+string(coh)+"."+string(mah),""); - obj_ini.mobi[coh,mah]=ini_read_string("Mar","mb"+string(coh)+"."+string(mah),""); - - obj_ini.age[coh,mah]=ini_read_real("Mar","ag"+string(coh)+"."+string(mah),0); - obj_ini.spe[coh,mah]=ini_read_string("Mar","spe"+string(coh)+"."+string(mah),""); - obj_ini.god[coh,mah]=ini_read_real("Mar","god"+string(coh)+"."+string(mah),0); - load_marine_struct(coh,mah); - unit = obj_ini.TTRPG[coh,mah]; - if (string_length(unit.weapon_one()) != 0 && string_length(string_digits(unit.weapon_one())) == string_length(unit.weapon_one())) { - obj_ini.wep1[coh, mah] = real(obj_ini.wep1[coh, mah]); - } - if (string_length(unit.weapon_two()) != 0 && string_length(string_digits(unit.weapon_two())) == string_length(unit.weapon_two())) { - obj_ini.wep2[coh, mah] = real(obj_ini.wep2[coh, mah]); - } - if (string_length(unit.gear()) != 0 && string_length(string_digits(unit.gear())) == string_length(unit.gear())) { - obj_ini.gear[coh, mah] = real(obj_ini.gear[coh, mah]); - } - if (string_length(unit.mobility_item()) != 0 && string_length(string_digits(unit.mobility_item())) == string_length(unit.mobility_item())) { - obj_ini.mobi[coh, mah] = real(obj_ini.mobi[coh, mah]); - } - if (string_length(unit.armour()) != 0 && string_length(string_digits(unit.armour())) == string_length(unit.armour())) { - obj_ini.armour[coh, mah] = real(obj_ini.armour[coh, mah]); - } + if (save_part=3) or (save_part=0){ + log_message("Loading INI"); + // Ini + var ini_save_data = obj_saveload.GameSave.Ini; + obj_ini.deserialize(ini_save_data); + log_message("INI loaded"); + + // Controller + log_message("Loading CONTROLLER"); + var save_data = obj_saveload.GameSave.Controller; + /// for some reason, obj_controller having it's deserialize as part of + /// the object doesnt want to work + with(obj_controller){ + var exclusions = ["specialist_point_handler", "location_viewer", "id"]; // skip automatic setting of certain vars, handle explicitly later + + // Automatic var setting + var all_names = struct_get_names(save_data); + var _len = array_length(all_names); + for(var i = 0; i < _len; i++){ + var var_name = all_names[i]; + if(array_contains(exclusions, var_name)){ + continue; + } + var loaded_value = struct_get(save_data, var_name); + // show_debug_message($"obj_controller var: {var_name} - val: {loaded_value}"); + try { + variable_struct_set(obj_controller, var_name, loaded_value); + } catch (e){ + show_debug_message(e); } } + specialist_point_handler = new SpecialistPointHandler(); + specialist_point_handler.calculate_research_points(); + location_viewer = new UnitQuickFindPanel(); + scr_colors_initialize(); + scr_shader_initialize(); + + global.star_name_colors[1] = make_color_rgb(body_colour_replace[0],body_colour_replace[1],body_colour_replace[2]); + } + log_message("CONTROLLER loaded"); - if (string_count(obj_ini.spe[0,1],"$")>0) then obj_controller.born_leader=1; - - coh=100;mah=-1; - repeat(21){mah+=1; - obj_ini.race[coh,mah]=ini_read_real("Mar","co"+string(coh)+"."+string(mah),0); - obj_ini.role[coh,mah]=ini_read_string("Mar","rol"+string(coh)+"."+string(mah),""); - obj_ini.wep1[coh,mah]=ini_read_string("Mar","w1"+string(coh)+"."+string(mah),""); - obj_ini.wep2[coh,mah]=ini_read_string("Mar","w2"+string(coh)+"."+string(mah),""); - obj_ini.armour[coh,mah]=ini_read_string("Mar","ar"+string(coh)+"."+string(mah),""); - obj_ini.gear[coh,mah]=ini_read_string("Mar","ge"+string(coh)+"."+string(mah),""); - obj_ini.mobi[coh,mah]=ini_read_string("Mar","mb"+string(coh)+"."+string(mah),""); - } - coh=102; - mah=-1; - repeat(21){mah+=1; - obj_ini.race[coh,mah]=ini_read_string("Mar","co"+string(coh)+"."+string(mah),0); - obj_ini.role[coh,mah]=ini_read_string("Mar","rol"+string(coh)+"."+string(mah),""); - obj_ini.wep1[coh,mah]=ini_read_string("Mar","w1"+string(coh)+"."+string(mah),""); - obj_ini.wep2[coh,mah]=ini_read_string("Mar","w2"+string(coh)+"."+string(mah),""); - obj_ini.armour[coh,mah]=ini_read_string("Mar","ar"+string(coh)+"."+string(mah),""); - obj_ini.gear[coh,mah]=ini_read_string("Mar","ge"+string(coh)+"."+string(mah),""); - obj_ini.mobi[coh,mah]=ini_read_string("Mar","mb"+string(coh)+"."+string(mah),""); - } - - obj_ini.squads = []; - var squad_fetch = ini_read_string("Mar","squads",""); - if (squad_fetch != ""){ - squad_fetch = json_parse(base64_decode(squad_fetch)); - for (i=0;i} unit where unit[0] is company and unit[1] is the position diff --git a/scripts/scr_save/scr_save.gml b/scripts/scr_save/scr_save.gml index e6427bd8e9..d876a53760 100644 --- a/scripts/scr_save/scr_save.gml +++ b/scripts/scr_save/scr_save.gml @@ -15,612 +15,125 @@ function ini_encode_and_json_advanced(ini_area, ini_code, value){ } function scr_save(save_part,save_id) { + var t1 = get_timer(); try{ - var num=0,tot=0; - num=0;tot=0; - - num=instance_number(obj_star); - instance_array[tot]=0; - - // if (file_exists("save1.ini")) then file_delete("save1.ini"); - // argument 0 = the part of the save to do - //save_id = the save ID - - if (save_part=1) or (save_part=0){ - scr_save_controller(save_id); - - } - - - if (save_part=2) or (save_part=0){ - log_message("Saving to slot "+string(save_id)+" - Part 2"); - ini_open($"save{save_id}.ini"); - // Stars - - var num=instance_number(obj_star); - instance_array=0; - for (var i=0; i=g){ - ini_write_real("Star","sr"+string(i)+"plan"+string(g),instance_array[i].planet[g]); - ini_write_real("Star","sr"+string(i)+"dispo"+string(g),instance_array[i].dispo[g]); - ini_write_string("Star","sr"+string(i)+"type"+string(g),instance_array[i].p_type[g]); - var save_features = []; - if (array_length(instance_array[i].p_feature[g])> 0){ - for (var f = 0;f < array_length(instance_array[i].p_feature[g]);f++){ - save_features[f]=0; - var copy_feature = instance_array[i].p_feature[g][f]; - var new_feature = {}; - var names = variable_struct_get_names(copy_feature); - for (var name = 0; name < array_length(names); name++) { - if (!is_method(copy_feature[$ names[name]])){ - variable_struct_set(new_feature, names[name],copy_feature[$ names[name]]) - } - } - save_features[f] = new_feature; - } - } - ini_write_string("Star","sr"+string(i)+"feat"+string(g),base64_encode(json_stringify(save_features))); - ini_write_string("Star","sr"+string(i)+"operatives"+string(g),base64_encode(json_stringify(instance_array[i].p_operatives[g]))); - ini_write_real("Star","sr"+string(i)+"own"+string(g),instance_array[i].p_owner[g]); - ini_write_real("Star","sr"+string(i)+"fir"+string(g),instance_array[i].p_first[g]); - ini_write_real("Star","sr"+string(i)+"popul"+string(g),instance_array[i].p_population[g]); - ini_write_real("Star","sr"+string(i)+"maxpop"+string(g),instance_array[i].p_max_population[g]); - ini_write_real("Star","sr"+string(i)+"large"+string(g),instance_array[i].p_large[g]); - ini_write_string("Star","sr"+string(i)+"pop"+string(g),instance_array[i].p_pop[g]); - ini_write_real("Star","sr"+string(i)+"guard"+string(g),instance_array[i].p_guardsmen[g]); - ini_write_real("Star","sr"+string(i)+"pdf"+string(g),instance_array[i].p_pdf[g]); - ini_write_real("Star","sr"+string(i)+"forti"+string(g),instance_array[i].p_fortified[g]); - ini_write_real("Star","sr"+string(i)+"stat"+string(g),instance_array[i].p_station[g]); - - ini_write_real("Star","sr"+string(i)+"play"+string(g),instance_array[i].p_player[g]); - if (instance_array[i].p_first[g]=1) or (instance_array[i].p_owner[g]=1){ - ini_write_real("Star","sr"+string(i)+"p_lasers"+string(g),instance_array[i].p_lasers[g]); - ini_write_real("Star","sr"+string(i)+"p_silo"+string(g),instance_array[i].p_silo[g]); - ini_write_real("Star","sr"+string(i)+"p_defenses"+string(g),instance_array[i].p_defenses[g]); - } - save_features = []; - if (array_length(instance_array[i].p_upgrades[g])> 0){ - for (var f = 0;f < array_length(instance_array[i].p_upgrades[g]);f++){ - save_features[f]=0; - var copy_feature = instance_array[i].p_upgrades[g][f]; - var new_feature = {}; - var names = variable_struct_get_names(copy_feature); - for (var name = 0; name < array_length(names); name++) { - if (!is_method(copy_feature[$ names[name]])){ - variable_struct_set(new_feature, names[name],copy_feature[$ names[name]]) - } - } - save_features[f] = new_feature; - } - } - ini_write_string("Star","sr"+string(i)+"upg"+string(g),base64_encode(json_stringify(save_features))); - ini_write_real("Star","sr"+string(i)+"or"+string(g),instance_array[i].p_orks[g]); - ini_write_real("Star","sr"+string(i)+"ta"+string(g),instance_array[i].p_tau[g]); - ini_write_real("Star","sr"+string(i)+"el"+string(g),instance_array[i].p_eldar[g]); - ini_write_real("Star","sr"+string(i)+"tr"+string(g),instance_array[i].p_traitors[g]); - ini_write_real("Star","sr"+string(i)+"ch"+string(g),instance_array[i].p_chaos[g]); - ini_write_real("Star","sr"+string(i)+"de"+string(g),instance_array[i].p_demons[g]); - ini_write_real("Star","sr"+string(i)+"si"+string(g),instance_array[i].p_sisters[g]); - ini_write_real("Star","sr"+string(i)+"ne"+string(g),instance_array[i].p_necrons[g]); - ini_write_real("Star","sr"+string(i)+"tyr"+string(g),instance_array[i].p_tyranids[g]); - ini_write_real("Star","sr"+string(i)+"halp"+string(g),instance_array[i].p_halp[g]); - - ini_write_real("Star","sr"+string(i)+"hurssy"+string(g),instance_array[i].p_hurssy[g]); - ini_write_real("Star","sr"+string(i)+"hurssy_time"+string(g),instance_array[i].p_hurssy_time[g]); - ini_write_real("Star","sr"+string(i)+"heresy"+string(g),instance_array[i].p_heresy[g]); - ini_write_real("Star","sr"+string(i)+"heresy_secret"+string(g),instance_array[i].p_heresy_secret[g]); - ini_write_string("Star","sr"+string(i)+"influence"+string(g),base64_encode(json_stringify(instance_array[i].p_influence[g]))); - ini_write_real("Star","sr"+string(i)+"raided"+string(g),instance_array[i].p_raided[g]); - - for (var p=0;p<8;p++){ - ini_write_string("Star",$"sr{i}prob{g}.{p}",instance_array[i].p_problem[g,p]); - ini_write_real("Star",$"sr{i}time{g}.{p}",instance_array[i].p_timer[g,p]); - ini_write_string("Star",$"sr{i}prob_other{g}.{p}",base64_encode(json_stringify(instance_array[i].p_problem_other_data[g,p]))); - } - } - } - } - - - // Temporary artifact objects - ini_write_real("Controller","temp_arti",instance_number(obj_temp_arti)); - num=instance_number(obj_temp_arti);instance_array=0; - for (var i=0; i=12 && hour<24) ? "PM":"AM"; + if (hour=0) then hour=12; + var mahg=minute; + if (mahg<10) then minute=$"0{mahg}"; + + obj_saveload.GameSave.Save = { + chapter_name: global.chapter_name, + sector_name: obj_ini.sector_name, + version: global.game_version, + play_time: play_time, + game_seed: global.game_seed, + use_custom_icon: obj_ini.use_custom_icon, + chapter_icon_sprite: global.chapter_icon_sprite, + chapter_icon_frame: global.chapter_icon_frame, + chapter_icon_path: global.chapter_icon_path, + icon_name: global.icon_name, + chapter_icon_filename: global.chapter_icon_filename, + date: string(month)+"/"+string(day)+"/"+string(year)+" ("+string(hour)+":"+string(minute)+" "+string(pm)+")", + founding: obj_ini.progenitor, + custom: global.custom, + stars: instance_number(obj_star), + p_fleets: instance_number(obj_p_fleet), + en_fleets: instance_number(obj_en_fleet), + sod: random_get_seed(), } - ini_write_string("Ini","artifact_struct"+string(g),base64_encode(json_stringify(new_artifact))); - } - - // - ini_encode_and_json("Ships","shi",obj_ini.ship); - ini_encode_and_json("Ships","shi_uid",obj_ini.ship_uid); - ini_encode_and_json("Ships","shi_class",obj_ini.ship_class); - ini_encode_and_json("Ships","shi_size",obj_ini.ship_size); - ini_encode_and_json("Ships","shi_leadership",obj_ini.ship_leadership); - ini_encode_and_json("Ships","shi_hp",obj_ini.ship_hp); - ini_encode_and_json("Ships","shi_maxhp",obj_ini.ship_maxhp); - ini_encode_and_json("Ships","shi_owner",obj_ini.ship_owner); - - - ini_encode_and_json("Ships","shi_location",obj_ini.ship_location); - ini_encode_and_json("Ships","shi_shields",obj_ini.ship_shields); - ini_encode_and_json("Ships","shi_conditions",obj_ini.ship_conditions); - ini_encode_and_json("Ships","shi_speed",obj_ini.ship_speed); - ini_encode_and_json("Ships","shi_turning",obj_ini.ship_turning); - - ini_encode_and_json("Ships","shi_front_ac",obj_ini.ship_front_armour); - ini_encode_and_json("Ships","shi_other_ac",obj_ini.ship_other_armour); - ini_encode_and_json("Ships","shi_weapons",obj_ini.ship_weapons); - - ini_encode_and_json("Ships","wep",obj_ini.ship_wep); - ini_encode_and_json("Ships","wep_facing",obj_ini.ship_wep_facing); - ini_encode_and_json("Ships","wep_condition",obj_ini.ship_wep_condition); - - ini_encode_and_json("Ships","shi_capacity",obj_ini.ship_capacity); - ini_encode_and_json("Ships","shi_carrying",obj_ini.ship_carrying); - ini_encode_and_json("Ships","shi_contents",obj_ini.ship_contents); - ini_encode_and_json("Ships","shi_turrets",obj_ini.ship_turrets); - - ini_close(); - } - - - if (save_part=3) or (save_part=0){log_message($"Saving to slot {save_id} - Part 3"); - ini_open($"save{save_id}.ini"); - var coh,mah,good; - for (coh=1;coh<=10;coh++){ - for (mah=1;mah<=100;mah++){ - if (obj_ini.veh_role[coh][mah]!=""){ - ini_write_real("Veh",$"co{coh}.{mah}",obj_ini.veh_race[coh,mah]); - ini_write_string("Veh",$"lo{coh}.{mah}",obj_ini.veh_loc[coh,mah]); - ini_write_string("Veh",$"rol{coh}.{mah}",obj_ini.veh_role[coh,mah]); - ini_write_real("Veh",$"lid{coh}.{mah}",obj_ini.veh_lid[coh,mah]); - ini_write_real("Veh",$"uid{coh}.{mah}",obj_ini.veh_uid[coh,mah]); - ini_write_real("Veh",$"wid{coh}.{mah}",obj_ini.veh_wid[coh,mah]); - - ini_write_string("Veh",$"w1{coh}.{mah}",obj_ini.veh_wep1[coh,mah]); - ini_write_string("Veh",$"w2{coh}.{mah}",obj_ini.veh_wep2[coh,mah]); - ini_write_string("Veh",$"w3{coh}.{mah}",obj_ini.veh_wep3[coh,mah]); - ini_write_string("Veh",$"up{coh}.{mah}",obj_ini.veh_upgrade[coh,mah]); - ini_write_string("Veh",$"ac{coh}.{mah}",obj_ini.veh_acc[coh,mah]); - - ini_write_real("Veh",$"hp{coh}.{mah}",obj_ini.veh_hp[coh,mah]); - ini_write_real("Veh",$"cha{coh}.{mah}",obj_ini.veh_chaos[coh,mah]); - ini_encode_and_json("Veh",$"last_ship{coh}.{mah}",obj_ini.last_ship[coh,mah]); - } - } - } - ini_close(); - } - - if (save_part=4) or (save_part=0){ - log_message("Saving to slot "+string(save_id)+" - Part 4"); - ini_open($"save{save_id}.ini"); - var coh,mah,good; - good=0;coh=100;mah=0; - log_message("Saving to slot "+string(save_id)+" - First Loop"); - repeat(30){mah+=1; - if (obj_ini.role[coh,mah]!=""){ - ini_write_real("Mar",$"co{coh}.{mah}",obj_ini.race[coh,mah]); - ini_write_string("Mar",$"num{coh}.{mah}",obj_ini.name[coh,mah]); - ini_write_string("Mar",$"rol{coh}.{mah}",obj_ini.role[coh,mah]); - ini_write_string("Mar",$"w1{coh}.{mah}",obj_ini.wep1[coh,mah]); - ini_write_string("Mar",$"w2{coh}.{mah}",obj_ini.wep2[coh,mah]); - ini_write_string("Mar",$"ar{coh}.{mah}",obj_ini.armour[coh,mah]); - ini_write_string("Mar",$"ge{coh}.{mah}",obj_ini.gear[coh,mah]); - ini_write_string("Mar",$"mb{coh}.{mah}",obj_ini.mobi[coh,mah]); - } - } - log_message("Saving to slot "+string(save_id)+" - Second Loop"); - for (coh=0;coh<=10;coh++){ - with (obj_ini){ - scr_company_order(coh); - } - for (mah=0;mah<=500;mah++){ - if (obj_ini.name[coh][mah] != ""){ - ini_write_real("Mar",$"co{coh}.{mah}",obj_ini.race[coh,mah]); - ini_write_string("Mar",$"lo{coh}.{mah}",obj_ini.loc[coh,mah]); - ini_write_string("Mar",$"num{coh}.{mah}",obj_ini.name[coh,mah]); - ini_write_string("Mar",$"rol{coh}.{mah}",obj_ini.role[coh,mah]); - - ini_write_string("Mar",$"w1{coh}.{mah}",obj_ini.wep1[coh,mah]); - ini_write_string("Mar",$"w2{coh}.{mah}",obj_ini.wep2[coh,mah]); - ini_write_string("Mar",$"ar{coh}.{mah}",obj_ini.armour[coh,mah]); - ini_write_string("Mar",$"ge{coh}.{mah}",obj_ini.gear[coh,mah]); - ini_write_string("Mar",$"mb{coh}.{mah}",obj_ini.mobi[coh,mah]); - ini_write_real("Mar",$"ag{coh}.{mah}",obj_ini.age[coh,mah]); - ini_write_string("Mar",$"spe{coh}.{mah}",obj_ini.spe[coh,mah]); - ini_write_real("Mar",$"god{coh}.{mah}",obj_ini.god[coh,mah]); - if (!is_struct(obj_ini.TTRPG[coh][mah])){ - TTRPG[coh][mah] = new TTRPG_stats("chapter", coh,mah, "blank"); - } else{ - ini_write_string("Mar",$"Struct{coh}.{mah}",base64_encode(jsonify_marine_struct(coh,mah))); - } - } else { - if (mah>0) then break; - } - } - } - log_message("Saving to slot "+string(save_id)+" - Squad Saving Start"); - var squad_copies = []; - if (array_length(obj_ini.squads)> 0){ - for (var i = 0;i < array_length(obj_ini.squads);i++){ - var _squad = obj_ini.squads[i].jsonify(); - array_push(squad_copies, _squad); + + /// STARS + var num=instance_number(obj_star); + for (var i=0; i=12 && hour<24) ? "PM":"AM"; - - if (hour=0) then hour=12; - - var mahg=minute; - if (mahg<10) then minute=$"0{mahg}"; - - // if (minute<10) then minute="0"+string(minute); - - ini_write_string("Save","date",string(month)+"/"+string(day)+"/"+string(year)+" ("+string(hour)+":"+string(minute)+" "+string(pm)+")"); - ini_write_real("Save","founding",obj_ini.progenitor); - // ini_write_string("Save","founding_secret",global.founding_secret); - ini_write_real("Save","custom",global.custom); - ini_write_real("Save","stars",instance_number(obj_star)); - ini_write_real("Save","p_fleets",instance_number(obj_p_fleet)); - ini_write_real("Save","en_fleets",instance_number(obj_en_fleet)); - ini_write_real("Save","sod",random_get_seed()); - ini_write_real("Save","corrupt",1); + // obj_controller variables here ini_write_real("boolean", "cheat_req", global.cheat_req); ini_write_real("boolean", "cheat_gene", global.cheat_gene); diff --git a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml index 6fb8667e58..2c4944f801 100644 --- a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml +++ b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml @@ -84,7 +84,7 @@ function SpecialistPointHandler() constructor{ forge_string += $"Techmarines: +{floor(forge_points)}#"; forge_points-=tech_points_used; forge_string += $"Vehicle Repairs:#"; - forge_string += $" Combat Repairs : {forge_veh_maintenance.repairs}\n"; + forge_string += $" Combat Repairs : {forge_veh_maintenance.repairs}#"; if (struct_exists(forge_veh_maintenance, "land_raider")){ forge_string += $" Land Raider Maintenance: -{forge_veh_maintenance.land_raider}#"; forge_points-=forge_veh_maintenance.land_raider; diff --git a/scripts/scr_squads/scr_squads.gml b/scripts/scr_squads/scr_squads.gml index 85a53e0807..4d6ad9238f 100644 --- a/scripts/scr_squads/scr_squads.gml +++ b/scripts/scr_squads/scr_squads.gml @@ -154,6 +154,8 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ in future i'd like to tailer these to marine skill sets e.g the marines with the best ranged stats get given the best ranged equipment */ static sort_squad_loadout = function(from_armoury=true, to_armoury=true){ + var unit; + var required_load, unit_type, load_out_name, load_out_areas, load_out_slot,load_item, optional_load, item_to_add; squad_unit_types = find_squad_unit_types(); var full_squad_data = obj_ini.squad_types[$ type]; @@ -434,7 +436,7 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ life_members++; } // for saving squads - static jsonify = function(){ + static jsonify = function(stringify = true){ var copy_struct = self; //grab marine structure var new_struct = {}; var copy_part; @@ -445,7 +447,11 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ variable_struct_set(new_struct, names[name],copy_part); //if key value is not a method add to copy structure } } - return json_stringify(new_struct); + if(stringify){ + return json_stringify(new_struct); + } else { + return new_struct; + } } //function for loading in squad save data @@ -462,6 +468,7 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ var locations = []; var system = "" var unit_loc; + var unit; var same_system = true; var same_loc_type = true; var loc_type = false; @@ -534,6 +541,7 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ //this means the highest ranking dude in a squad will always be the squad leader //failing that the highest experience dude static determine_leader = function(){ + var unit; var member_length = array_length(members); var hierarchy = role_hierarchy(); var leader_hier_pos=array_length(hierarchy); @@ -607,6 +615,7 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ } static member_loop = function(member_func, data_pack){ + var unit; member_length = array_length(members); for (var i=0;i Date: Fri, 4 Apr 2025 05:43:42 +0300 Subject: [PATCH 02/12] fix: Typo in saveload --- objects/obj_saveload/Alarm_0.gml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objects/obj_saveload/Alarm_0.gml b/objects/obj_saveload/Alarm_0.gml index b5c797aba8..b79daff98b 100644 --- a/objects/obj_saveload/Alarm_0.gml +++ b/objects/obj_saveload/Alarm_0.gml @@ -48,7 +48,6 @@ if (save_part == 2) { } if (save_part == 1) { - if (file_exists("save" + string(save_number) + ".json")) { if (file_exists($"save{save_number}.json")) { file_delete($"save{save_number}.json"); } @@ -60,6 +59,7 @@ if (save_part == 1) { trickle = 2; txt = "Preparing"; } + if (load_part==6){ txt="Praise to the Machine God"; if (global.restart>0) then txt="Praise be to the Emperor"; From af7d670a1c89436b726c4ad29192abadd125b207 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Sat, 5 Apr 2025 09:44:37 +0300 Subject: [PATCH 03/12] fix: Leftover ini save bits --- objects/obj_popup/Step_0.gml | 2 +- objects/obj_saveload/Draw_0.gml | 43 +++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/objects/obj_popup/Step_0.gml b/objects/obj_popup/Step_0.gml index 504097a564..c90f2aa9d3 100644 --- a/objects/obj_popup/Step_0.gml +++ b/objects/obj_popup/Step_0.gml @@ -50,7 +50,7 @@ try { if ((image == "fuklaw") && (save > 0)) { if (press == 1) { var del = obj_saveload.save[save]; - var _save_file = $"save{del}.ini"; + var _save_file = $"save{del}.json"; if (file_exists(_save_file)) { file_delete(_save_file); if (file_exists($"save{del}log.ini")) { diff --git a/objects/obj_saveload/Draw_0.gml b/objects/obj_saveload/Draw_0.gml index bed4329373..79f4bf24dc 100644 --- a/objects/obj_saveload/Draw_0.gml +++ b/objects/obj_saveload/Draw_0.gml @@ -151,20 +151,31 @@ if (menu=1) or (menu=2){// This is the other one draw_set_font(fnt_40k_30b);draw_set_halign(fa_center); - if (save[o]>0){ + if (save[o] > 0) { // Delete Data draw_set_alpha(1); - draw_set_color(c_gray);draw_rectangle(x2+807,y2+113,x2+951,y2+146,0); - draw_set_color(c_black);draw_rectangle(x2+807,y2+113,x2+951,y2+146,1); - draw_text_transformed(x2+879,y2+117,string_hash_to_newline("Delete Game"),0.7,0.7,0); - if (scr_hit(x2+807,y2+113,x2+951,y2+146)=true){ - draw_set_alpha(0.1);draw_set_color(c_white);draw_rectangle(x2+807,y2+113,x2+951,y2+146,0);draw_set_alpha(1); - if (mouse_left>=1) and (!instance_exists(obj_popup)) and (cooldown<=0){// Clear - var com;com=instance_create(0,0,obj_popup); - com.image="fuklaw";com.title="Delete Save Game?"; - com.text="Are you sure you wish to delete Save "+string(save[o])+"- "+string(save_chapter[save[o]])+"?"; - com.option1="Yes";com.option2="No";com.save=o; - com.woopwoopwoop=menu;com.owner=top; + draw_set_color(c_gray); + draw_rectangle(x2 + 807, y2 + 113, x2 + 951, y2 + 146, 0); + draw_set_color(c_black); + draw_rectangle(x2 + 807, y2 + 113, x2 + 951, y2 + 146, 1); + draw_text_transformed(x2 + 879, y2 + 117, string_hash_to_newline("Delete Game"), 0.7, 0.7, 0); + if (scr_hit(x2 + 807, y2 + 113, x2 + 951, y2 + 146) == true) { + draw_set_alpha(0.1); + draw_set_color(c_white); + draw_rectangle(x2 + 807, y2 + 113, x2 + 951, y2 + 146, 0); + draw_set_alpha(1); + if ((mouse_left >= 1) && (!instance_exists(obj_popup)) && (cooldown <= 0)) { + // Clear + var com; + com = instance_create(0, 0, obj_popup); + com.image = "fuklaw"; + com.title = "Delete Save Game?"; + com.text = "Are you sure you wish to delete Save " + string(save[o]) + "- " + string(save_chapter[save[o]]) + "?"; + com.option1 = "Yes"; + com.option2 = "No"; + com.save = o; + com.woopwoopwoop = menu; + com.owner = top; } } } @@ -178,7 +189,7 @@ if (menu=1) or (menu=2){// This is the other one if (scr_hit(x2+977,y2+113,x2+1121,y2+146)=true){ draw_set_alpha(0.1);draw_set_color(c_white);draw_rectangle(x2+977,y2+113,x2+1121,y2+146,0);draw_set_alpha(1); if (mouse_left>=1) and (!instance_exists(obj_popup)) and (cooldown<=0){ - if (file_exists("save"+string(save[o])+".ini")){// Resets the data + if (file_exists("save"+string(save[o])+".json")){// Resets the data global.restart=1;global.load=save[o]; menu=0;load_part=1;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); @@ -212,7 +223,7 @@ if (menu=1) or (menu=2){// This is the other one if (mouse_left>=1) and (!instance_exists(obj_popup)) and (cooldown<=0){// Load global.load=save[o];menu=0;load_part=1;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); - // show_message("loading 'save"+string(save[o])+".ini'"); + // show_message("loading 'save"+string(save[o])+".json'"); if (instance_exists(obj_main_menu)){ with(obj_main_menu){ @@ -245,7 +256,7 @@ if (menu=1) or (menu=2){// This is the other one if (instance_exists(obj_main_menu)){with(obj_main_menu){part_particles_clear(p_system);}} // If open slot then set the save.ini to the maximum - if (!file_exists("save"+string(save[o])+".ini")) or (save[o]=0) and (onceh=0){ + if (!file_exists("save"+string(save[o])+".json")) or (save[o]=0) and (onceh=0){ save_part=1;menu=0;save_number=max_ini;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); with(obj_new_button){instance_destroy();} with(obj_ingame_menu){instance_destroy();} @@ -253,7 +264,7 @@ if (menu=1) or (menu=2){// This is the other one alarm[0]=1;onceh=1; } // If file exists then overright - if (file_exists("save"+string(save[o])+".ini")){file_delete("save"+string(save[o])+".ini"); + if (file_exists("save"+string(save[o])+".json")){file_delete("save"+string(save[o])+".json"); if (file_exists("screen"+string(save[o])+".png")) then file_delete("screen"+string(save[o])+".png"); save_part=1;menu=0;save_number=o;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); with(obj_new_button){instance_destroy();} From cdc6f6916597fceae091c43d35f98c6365b01b32 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 00:01:50 +0300 Subject: [PATCH 04/12] refactor: Serialization improvements; Readable save files (#680) --- ChapterMaster.yyp | 1 + objects/obj_controller/Create_0.gml | 38 +------------ objects/obj_en_fleet/Create_0.gml | 34 +----------- objects/obj_ini/Create_0.gml | 36 +----------- objects/obj_p_fleet/Create_0.gml | 34 +----------- objects/obj_star/Create_0.gml | 55 +++---------------- .../scr_marine_struct/scr_marine_struct.gml | 2 +- scripts/scr_save/scr_save.gml | 2 +- .../scr_serialization_functions.gml | 47 ++++++++++++++++ .../scr_serialization_functions.yy | 13 +++++ scripts/scr_squads/scr_squads.gml | 2 +- .../scr_string_functions.gml | 13 +++++ 12 files changed, 94 insertions(+), 183 deletions(-) create mode 100644 scripts/scr_serialization_functions/scr_serialization_functions.gml create mode 100644 scripts/scr_serialization_functions/scr_serialization_functions.yy diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index fce1f95ed2..835b4a247e 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -815,6 +815,7 @@ {"id":{"name":"scr_save_controller","path":"scripts/scr_save_controller/scr_save_controller.yy",},}, {"id":{"name":"scr_save","path":"scripts/scr_save/scr_save.yy",},}, {"id":{"name":"scr_scrollbar","path":"scripts/scr_scrollbar/scr_scrollbar.yy",},}, + {"id":{"name":"scr_serialization_functions","path":"scripts/scr_serialization_functions/scr_serialization_functions.yy",},}, {"id":{"name":"scr_shader_initialize","path":"scripts/scr_shader_initialize/scr_shader_initialize.yy",},}, {"id":{"name":"scr_ship_battle","path":"scripts/scr_ship_battle/scr_ship_battle.yy",},}, {"id":{"name":"scr_ship_count","path":"scripts/scr_ship_count/scr_ship_count.yy",},}, diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index bbfa51dfbb..66365700b4 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -1476,42 +1476,10 @@ serialize = function(){ } var excluded_from_save = ["temp", "serialize", "deserialize", "build_chaos_gods", "company_data","menu_buttons", "location_viewer", "production_research_pathways", "specialist_point_handler", "spec_train_data"] + var excluded_from_save_start = ["restart_"]; + + copy_serializable_fields(object_controller, save_data, excluded_from_save, excluded_from_save_start); - /// Check all object variable values types and save the simple ones dynamically. - /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. - /// non-simple types are structs, functions, methods - /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. - var all_names = struct_get_names(object_controller); - var _len = array_length(all_names); - for(var i = 0; i < _len; i++){ - var var_name = all_names[i]; - if(array_contains(excluded_from_save, var_name)){ - continue; - } - if(struct_exists(save_data, var_name)){ - continue; //already added above - } - if(string_starts_with(var_name, "restart_")){ - continue; - } - if(is_basic_variable(object_controller[$var_name])){ - variable_struct_set(save_data, var_name, object_controller[$var_name]); - } - if(is_array(object_controller[$var_name])){ - var _check_arr = object_controller[$var_name]; - var _ok_array = is_basic_array(_check_arr, 2); - if(!_ok_array){ - log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_controller"); - } else { - variable_struct_set(save_data, var_name, object_controller[$var_name]); - } - } - if(is_struct(object_controller[$var_name])){ - if(!struct_exists(save_data, var_name)){ - log_warning($"obj_ini.serialze() - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); - } - } - } return save_data; } diff --git a/objects/obj_en_fleet/Create_0.gml b/objects/obj_en_fleet/Create_0.gml index 8f5412668c..fa1dba0041 100644 --- a/objects/obj_en_fleet/Create_0.gml +++ b/objects/obj_en_fleet/Create_0.gml @@ -83,39 +83,7 @@ serialize = function(){ var excluded_from_save = ["temp", "serialize", "deserialize", "cargo_data"] - /// Check all object variable values types and save the simple ones dynamically. - /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. - /// non-simple types are structs, functions, methods - /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. - var all_names = struct_get_names(object_fleet); - var _len = array_length(all_names); - for(var i = 0; i < _len; i++){ - var var_name = all_names[i]; - if(array_contains(excluded_from_save, var_name)){ - continue; - } - if(struct_exists(save_data, var_name)){ - continue; //already added above - } - if(is_basic_variable(object_fleet[$var_name])){ - variable_struct_set(save_data, var_name, object_fleet[$var_name]); - } - if(is_array(object_fleet[$var_name])){ - var _check_arr = object_fleet[$var_name]; - var _ok_array = is_basic_array(_check_arr, 2); - if(!_ok_array){ - log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_en_fleet"); - } else { - variable_struct_set(save_data, var_name, object_fleet[$var_name]); - } - } - if(is_struct(object_fleet[$var_name])){ - if(!struct_exists(save_data, var_name)){ - log_warning($"WARNING: obj_ini.serialze() - obj_en_fleet - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); - } - } - } - + copy_serializable_fields(object_fleet, save_data, excluded_from_save); return save_data; } diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 4fd8f816e0..49b2937cfe 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -164,40 +164,10 @@ serialize = function(){ save_data.last_ship = object_ini.last_ship; } - var excluded_from_save = ["temp", "serialize", "deserialize", "load_default_gear", "role_spawn_buffs", "TTRPG", "squads", "squad_types", "marines", "last_ship"] + var excluded_from_save = ["temp", "serialize", "deserialize", "load_default_gear", "role_spawn_buffs", "TTRPG", "squads", "squad_types", "marines", "last_ship"]; + + copy_serializable_fields(object_ini, save_data, excluded_from_save); - /// Check all object variable values types and save the simple ones dynamically. - /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. - /// non-simple types are structs, functions, methods - /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. - var all_names = struct_get_names(object_ini); - var _len = array_length(all_names); - for(var i = 0; i < _len; i++){ - var var_name = all_names[i]; - if(array_contains(excluded_from_save, var_name)){ - continue; - } - if(struct_exists(save_data, var_name)){ - continue; //already added above - } - if(is_basic_variable(object_ini[$var_name])){ - variable_struct_set(save_data, var_name, object_ini[$var_name]); - } - if(is_array(object_ini[$var_name])){ - var _check_arr = object_ini[$var_name]; - var _ok_array = is_basic_array(_check_arr, 2); - if(!_ok_array){ - log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_ini"); - } else { - variable_struct_set(save_data, var_name, object_ini[$var_name]); - } - } - if(is_struct(object_ini[$var_name])){ - if(!struct_exists(save_data, var_name)){ - log_warning($"WARNING: obj_ini.serialze() - obj_ini - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); - } - } - } return save_data; } diff --git a/objects/obj_p_fleet/Create_0.gml b/objects/obj_p_fleet/Create_0.gml index 7a503a4b01..d7f3e2e404 100644 --- a/objects/obj_p_fleet/Create_0.gml +++ b/objects/obj_p_fleet/Create_0.gml @@ -69,39 +69,7 @@ serialize = function(){ } var excluded_from_save = ["temp", "serialize", "deserialize"] - /// Check all object variable values types and save the simple ones dynamically. - /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. - /// non-simple types are structs, functions, methods - /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. - var all_names = struct_get_names(object_fleet); - var _len = array_length(all_names); - for(var i = 0; i < _len; i++){ - var var_name = all_names[i]; - if(array_contains(excluded_from_save, var_name)){ - continue; - } - if(struct_exists(save_data, var_name)){ - continue; //already added above - } - if(is_basic_variable(object_fleet[$var_name])){ - variable_struct_set(save_data, var_name, object_fleet[$var_name]); - } - if(is_array(object_fleet[$var_name])){ - var _check_arr = object_fleet[$var_name]; - var _ok_array = is_basic_array(_check_arr, 2); - if(!_ok_array){ - log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - obj_p_fleet"); - } else { - variable_struct_set(save_data, var_name, object_fleet[$var_name]); - } - } - if(is_struct(object_fleet[$var_name])){ - if(!struct_exists(save_data, var_name)){ - log_warning($"WARNING: obj_ini.serialze() - obj_p_fleet - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); - } - } - } - + copy_serializable_fields(object_fleet, save_data, excluded_from_save); return save_data; } diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index 1ee766aa0b..bce5dacdff 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -139,55 +139,21 @@ serialize = function(){ obj: object_get_name(object_index), x, y, - present_fleet: base64_encode(json_stringify(object_star.present_fleet)), + present_fleet: json_stringify(object_star.present_fleet, true), planet_data: planet_data, } if(struct_exists(object_star, "system_garrison")){ - save_data.system_garrison = base64_encode(json_stringify(object_star.system_garrison)); + save_data.system_garrison = json_stringify(object_star.system_garrison, true); } if(struct_exists(object_star, "system_sabatours")){ - save_data.system_sabatours = base64_encode(json_stringify(object_star.system_sabatours)); + save_data.system_sabatours = json_stringify(object_star.system_sabatours, true); } - var excluded_from_save = ["temp", "serialize", "deserialize", "arraysum"] + var excluded_from_save = ["temp", "serialize", "deserialize", "arraysum"]; + var excluded_from_save_start = ["p_"]; - /// Check all object variable values types and save the simple ones dynamically. - /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. - /// non-simple types are structs, functions, methods - /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. - var all_names = struct_get_names(object_star); - var _len = array_length(all_names); - for(var i = 0; i < _len; i++){ - var var_name = all_names[i]; - if(array_contains(excluded_from_save, var_name)){ - continue; - } - if(string_starts_with(var_name, "p_")){ - continue; //handled in planet_data above - } - if(struct_exists(save_data, var_name)){ - continue; //already added above - } - if(is_basic_variable(object_star[$var_name])){ - variable_struct_set(save_data, var_name, object_star[$var_name]); - } - if(is_array(object_star[$var_name])){ - var _check_arr = object_star[$var_name]; - var _ok_array = true; - var _ok_array = is_basic_array(_check_arr, 2); - if(!_ok_array){ - log_warning($"Bad array save: '{var_name}' internal type found was not a simple type and should probably have it's own serialize functino - object_star"); - } else { - variable_struct_set(save_data, var_name, object_star[$var_name]); - } - } - if(is_struct(object_star[$var_name])){ - if(!struct_exists(save_data, var_name)){ - log_warning($"WARNING: obj_ini.serialze() - obj_star - object contains struct variable '{var_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); - } - } - } + copy_serializable_fields(object_star, save_data, excluded_from_save, excluded_from_save_start); return save_data; } @@ -209,8 +175,7 @@ function deserialize(save_data){ // Set explicit vars here if(struct_exists(save_data, "present_fleet")){ - var encoded_fleet = save_data.present_fleet; - variable_struct_set(self, "present_fleet", json_parse(base64_decode(encoded_fleet))); + variable_struct_set(self, "present_fleet", json_parse(save_data.present_fleet)); } if(struct_exists(save_data, "planet_data")){ @@ -233,12 +198,10 @@ function deserialize(save_data){ } if(struct_exists(save_data, "system_sabatours")){ - var encoded_sabatours = save_data.system_sabatours; - variable_struct_set(self, "system_sabatours", json_parse(base64_decode(encoded_sabatours))); + variable_struct_set(self, "system_sabatours", json_parse(save_data.system_sabatours)); } if(struct_exists(save_data, "system_garrison")){ - var encoded_garrison = save_data.system_garrison; - variable_struct_set(self, "system_garrison", json_parse(base64_decode(encoded_garrison))); + variable_struct_set(self, "system_garrison", json_parse(save_data.system_garrison)); } } diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 6d571fb0e7..b6ec836b65 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -2283,7 +2283,7 @@ function jsonify_marine_struct(company, marine, stringify=true) { } } if(stringify){ - return json_stringify(new_marine); + return json_stringify(new_marine, true); } else { return new_marine; } diff --git a/scripts/scr_save/scr_save.gml b/scripts/scr_save/scr_save.gml index d876a53760..9366d9d826 100644 --- a/scripts/scr_save/scr_save.gml +++ b/scripts/scr_save/scr_save.gml @@ -117,7 +117,7 @@ function scr_save(save_part,save_id) { obj_saveload.save[save_id]=1; - var _gamesave_string = json_stringify(obj_saveload.GameSave); + var _gamesave_string = json_stringify(obj_saveload.GameSave, true); var _gamesave_buffer = buffer_create(string_byte_length(_gamesave_string) + 1, buffer_fixed, 1); var filename = $"save{save_id}.json"; diff --git a/scripts/scr_serialization_functions/scr_serialization_functions.gml b/scripts/scr_serialization_functions/scr_serialization_functions.gml new file mode 100644 index 0000000000..9ecd75fe91 --- /dev/null +++ b/scripts/scr_serialization_functions/scr_serialization_functions.gml @@ -0,0 +1,47 @@ +/// @desc Copies simple (serializable) variables from one struct to another, excluding specified names and prefixes. Useful for building save-data structs. +/// @param {struct} _source - The struct to copy variables from. +/// @param {struct} _destination - The struct to copy variables into. +/// @param {array} _exclude - List of variable names to exclude. +/// @param {array} _exclude_start - List of string prefixes; variables starting with any of these will be excluded. +function copy_serializable_fields(_source, _destination, _exclude = [], _exclude_start = []) { + /// Check all object variable values types and save the simple ones dynamically. + /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. + /// non-simple types are structs, functions, methods + /// functions and methods will be ignored completely, structs to be manually serialized/deserialised. + + var _all_names = struct_get_names(_source); + var _len = array_length(_all_names); + + for (var i = 0; i < _len; i++) { + var _field_name = _all_names[i]; + var _field_value = _source[$ _field_name]; + + if (array_contains(_exclude, _field_name)) { + continue; // excluded by the full name + } + + if (string_starts_with_any(_field_name, _exclude_start)) { + continue; // excluded by the prefix + } + + if (struct_exists(_destination, _field_name)) { + continue; // already added + } + + if (is_basic_variable(_field_value)) { + variable_struct_set(_destination, _field_name, _field_value); + } + + if (is_array(_field_value)) { + if (!is_basic_array(_field_value, 2)) { + var _source_obj_name = struct_exists(_source, "object_index") ? object_get_name(_source.object_index) : ""; + log_warning($"Bad array save: '{_field_name}' internal type found was not a simple type and should probably have it's own serialize function - {_source_obj_name}"); + } else { + variable_struct_set(_destination, _field_name, _field_value); + } + } else if (is_struct(_field_value) && !struct_exists(_destination, _field_name)) { + var _source_obj_name = struct_exists(_source, "object_index") ? object_get_name(_source.object_index) : ""; + log_warning($"obj_ini.serialze() - {_source_obj_name} - object contains struct variable '{_field_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + } + } +} diff --git a/scripts/scr_serialization_functions/scr_serialization_functions.yy b/scripts/scr_serialization_functions/scr_serialization_functions.yy new file mode 100644 index 0000000000..15357345d7 --- /dev/null +++ b/scripts/scr_serialization_functions/scr_serialization_functions.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"scr_serialization_functions", + "isCompatibility":false, + "isDnD":false, + "name":"scr_serialization_functions", + "parent":{ + "name":"Scripts", + "path":"folders/Scripts.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/scr_squads/scr_squads.gml b/scripts/scr_squads/scr_squads.gml index 4d6ad9238f..7bf35df928 100644 --- a/scripts/scr_squads/scr_squads.gml +++ b/scripts/scr_squads/scr_squads.gml @@ -448,7 +448,7 @@ function UnitSquad(squad_type = undefined, company = undefined) constructor{ } } if(stringify){ - return json_stringify(new_struct); + return json_stringify(new_struct, true); } else { return new_struct; } diff --git a/scripts/scr_string_functions/scr_string_functions.gml b/scripts/scr_string_functions/scr_string_functions.gml index a408fced02..a38e10fca8 100644 --- a/scripts/scr_string_functions/scr_string_functions.gml +++ b/scripts/scr_string_functions/scr_string_functions.gml @@ -311,3 +311,16 @@ function smart_verb(_verb, _variable) { return _result; } + +/// @desc Checks if a string starts with any prefix in the given array. +/// @param {string} _str - The string to check. +/// @param {array} _prefixes - An array of string prefixes to match against. +/// @returns {boolean} +function string_starts_with_any(_str, _prefixes) { + for (var i = 0, _len = array_length(_prefixes); i < _len; ++i) { + if (string_starts_with(_str, _prefixes[i])) { + return true; + } + } + return false; +} From 634e6edd47d0703253665439953d896fc5252c82 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 00:15:41 +0300 Subject: [PATCH 05/12] feat: Save Files separate folder --- objects/obj_popup/Step_0.gml | 7 ++-- objects/obj_saveload/Alarm_0.gml | 10 +++--- objects/obj_saveload/Alarm_2.gml | 2 +- objects/obj_saveload/Alarm_4.gml | 36 ++++++++++++++------- objects/obj_saveload/Create_0.gml | 22 +++++++++---- objects/obj_saveload/Draw_0.gml | 29 ++++++++++++----- objects/obj_saveload/Mouse_60.gml | 35 ++++++++++++++------ objects/obj_saveload/Mouse_61.gml | 16 ++++++--- scripts/__init_external/__init_external.gml | 5 +++ scripts/scr_load/scr_load.gml | 2 +- scripts/scr_save/scr_save.gml | 2 +- 11 files changed, 114 insertions(+), 52 deletions(-) diff --git a/objects/obj_popup/Step_0.gml b/objects/obj_popup/Step_0.gml index c90f2aa9d3..d337aa9fa3 100644 --- a/objects/obj_popup/Step_0.gml +++ b/objects/obj_popup/Step_0.gml @@ -50,14 +50,15 @@ try { if ((image == "fuklaw") && (save > 0)) { if (press == 1) { var del = obj_saveload.save[save]; - var _save_file = $"save{del}.json"; + var _save_file = string(PATH_save_files, del); + var _save_preview = string(PATH_save_previews, del); if (file_exists(_save_file)) { file_delete(_save_file); if (file_exists($"save{del}log.ini")) { file_delete($"save{del}log.ini"); } - if (file_exists($"screen{del}.png")) { - file_delete($"screen{del}.png"); + if (file_exists(_save_preview)) { + file_delete(_save_preview); } with (obj_saveload) { instance_destroy(); diff --git a/objects/obj_saveload/Alarm_0.gml b/objects/obj_saveload/Alarm_0.gml index b79daff98b..b5ea475873 100644 --- a/objects/obj_saveload/Alarm_0.gml +++ b/objects/obj_saveload/Alarm_0.gml @@ -48,11 +48,11 @@ if (save_part == 2) { } if (save_part == 1) { - if (file_exists($"save{save_number}.json")) { - file_delete($"save{save_number}.json"); + if (file_exists(string(PATH_save_files, save_number))) { + file_delete(string(PATH_save_files, save_number)); } - if (file_exists($"screen{save_number}.png")) { - file_delete($"screen{save_number}.png"); + if (file_exists(string(PATH_save_previews, save_number))) { + file_delete(string(PATH_save_previews, save_number)); } obj_saveload.save[save_number] = 0; save_part += 1; @@ -128,7 +128,7 @@ if (load_part == 2) { } if (load_part == 1) { - if (file_exists($"save{global.load}.json")) { + if (file_exists(string(PATH_save_files, global.load))) { load_part += 1; trickle = 2; txt = "Preparing"; diff --git a/objects/obj_saveload/Alarm_2.gml b/objects/obj_saveload/Alarm_2.gml index d89363e8ed..12761deac5 100644 --- a/objects/obj_saveload/Alarm_2.gml +++ b/objects/obj_saveload/Alarm_2.gml @@ -1,5 +1,5 @@ -screen_save("screen"+string(save_number)+".png"); +screen_save(string(PATH_save_previews, save_number)); alarm[3]=1; diff --git a/objects/obj_saveload/Alarm_4.gml b/objects/obj_saveload/Alarm_4.gml index 47ec398f89..96bf520e3a 100644 --- a/objects/obj_saveload/Alarm_4.gml +++ b/objects/obj_saveload/Alarm_4.gml @@ -1,12 +1,24 @@ - - -if (sprite_exists(img1)){sprite_delete(img1);} -if (sprite_exists(img2)){sprite_delete(img2);} -if (sprite_exists(img3)){sprite_delete(img3);} -if (sprite_exists(img4)){sprite_delete(img4);} -if (file_exists(working_directory + "\\screen"+string(save[top])+".png")) then img1=sprite_add(working_directory + "\\screen"+string(save[top])+".png",1,0,0,0,0); -if (file_exists(working_directory + "\\screen"+string(save[top+1])+".png")) then img2=sprite_add(working_directory + "\\screen"+string(save[top+1])+".png",1,0,0,0,0); -if (file_exists(working_directory + "\\screen"+string(save[top+2])+".png")) then img3=sprite_add(working_directory + "\\screen"+string(save[top+2])+".png",1,0,0,0,0); -if (file_exists(working_directory + "\\screen"+string(save[top+3])+".png")) then img4=sprite_add(working_directory + "\\screen"+string(save[top+3])+".png",1,0,0,0,0); - - +if (sprite_exists(img1)) { + sprite_delete(img1); +} +if (sprite_exists(img2)) { + sprite_delete(img2); +} +if (sprite_exists(img3)) { + sprite_delete(img3); +} +if (sprite_exists(img4)) { + sprite_delete(img4); +} +if (file_exists(string(PATH_save_previews, save[top]))) { + img1 = sprite_add(string(PATH_save_previews, save[top]), 1, 0, 0, 0, 0); +} +if (file_exists(string(PATH_save_previews, save[top + 1]) + ".png")) { + img2 = sprite_add(string(PATH_save_previews, save[top + 1]), 1, 0, 0, 0, 0); +} +if (file_exists(string(PATH_save_previews, save[top + 2]) + ".png")) { + img3 = sprite_add(string(PATH_save_previews, save[top + 2]), 1, 0, 0, 0, 0); +} +if (file_exists(string(PATH_save_previews, save[top + 3]))) { + img4 = sprite_add(string(PATH_save_previews, save[top + 3]), 1, 0, 0, 0, 0); +} diff --git a/objects/obj_saveload/Create_0.gml b/objects/obj_saveload/Create_0.gml index 7f8aa458a1..2dccd61d34 100644 --- a/objects/obj_saveload/Create_0.gml +++ b/objects/obj_saveload/Create_0.gml @@ -53,11 +53,11 @@ repeat(201){i+=1; } i=0; repeat(100){i+=1; - if (file_exists($"save{i}.json")){ + if (file_exists(string(PATH_save_files, i))){ saves+=1;save[saves]=i; } - if (!file_exists($"save{i}.json")) and (i>0) and (max_ini=0) then max_ini=i; - if (file_exists($"save{i+1}.json")) and (max_ini>0) then max_ini=0;} + if (!file_exists(string(PATH_save_files, i))) and (i>0) and (max_ini=0) then max_ini=i; + if (file_exists(string(PATH_save_files, i + 1))) and (max_ini>0) then max_ini=0;} first_open=saves+1; @@ -103,10 +103,18 @@ if (file_exists("saves.ini")){ } - if (file_exists(working_directory + "\\screen"+string(save[1])+".png")) then img1=sprite_add(working_directory + "\\screen"+string(save[1])+".png",1,0,0,0,0); - if (file_exists(working_directory + "\\screen"+string(save[2])+".png")) then img2=sprite_add(working_directory + "\\screen"+string(save[2])+".png",1,0,0,0,0); - if (file_exists(working_directory + "\\screen"+string(save[3])+".png")) then img3=sprite_add(working_directory + "\\screen"+string(save[3])+".png",1,0,0,0,0); - if (file_exists(working_directory + "\\screen"+string(save[4])+".png")) then img4=sprite_add(working_directory + "\\screen"+string(save[4])+".png",1,0,0,0,0); + if (file_exists(string(PATH_save_previews, save[1]))) { + img1 = sprite_add(string(PATH_save_previews, save[1]), 1, 0, 0, 0, 0); + } + if (file_exists(string(PATH_save_previews, save[2]))) { + img2 = sprite_add(string(PATH_save_previews, save[2]), 1, 0, 0, 0, 0); + } + if (file_exists(string(PATH_save_previews, save[3]))) { + img3 = sprite_add(string(PATH_save_previews, save[3]), 1, 0, 0, 0, 0); + } + if (file_exists(string(PATH_save_previews, save[4]))) { + img4 = sprite_add(string(PATH_save_previews, save[4]), 1, 0, 0, 0, 0); + } ini_close(); diff --git a/objects/obj_saveload/Draw_0.gml b/objects/obj_saveload/Draw_0.gml index 79f4bf24dc..575a63a5e4 100644 --- a/objects/obj_saveload/Draw_0.gml +++ b/objects/obj_saveload/Draw_0.gml @@ -189,7 +189,7 @@ if (menu=1) or (menu=2){// This is the other one if (scr_hit(x2+977,y2+113,x2+1121,y2+146)=true){ draw_set_alpha(0.1);draw_set_color(c_white);draw_rectangle(x2+977,y2+113,x2+1121,y2+146,0);draw_set_alpha(1); if (mouse_left>=1) and (!instance_exists(obj_popup)) and (cooldown<=0){ - if (file_exists("save"+string(save[o])+".json")){// Resets the data + if (file_exists(string(PATH_save_files, save[o]))) { // Resets the data global.restart=1;global.load=save[o]; menu=0;load_part=1;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); @@ -256,7 +256,7 @@ if (menu=1) or (menu=2){// This is the other one if (instance_exists(obj_main_menu)){with(obj_main_menu){part_particles_clear(p_system);}} // If open slot then set the save.ini to the maximum - if (!file_exists("save"+string(save[o])+".json")) or (save[o]=0) and (onceh=0){ + if (!file_exists(string(PATH_save_files, save[o])) || (save[o] == 0) && (onceh == 0)) { save_part=1;menu=0;save_number=max_ini;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); with(obj_new_button){instance_destroy();} with(obj_ingame_menu){instance_destroy();} @@ -264,14 +264,27 @@ if (menu=1) or (menu=2){// This is the other one alarm[0]=1;onceh=1; } // If file exists then overright - if (file_exists("save"+string(save[o])+".json")){file_delete("save"+string(save[o])+".json"); - if (file_exists("screen"+string(save[o])+".png")) then file_delete("screen"+string(save[o])+".png"); - save_part=1;menu=0;save_number=o;obj_cursor.image_alpha=0;splash=choose(0,1,2,3,4); - with(obj_new_button){instance_destroy();} - with(obj_ingame_menu){instance_destroy();} + if (file_exists(string(PATH_save_files, save[o]))) { + file_delete(string(PATH_save_files, save[o])); + if (file_exists(string(PATH_save_previews, save[o]))) { + file_delete(string(PATH_save_previews, save[o])); + } + save_part = 1; + menu = 0; + save_number = o; + obj_cursor.image_alpha = 0; + splash = choose(0, 1, 2, 3, 4); + with (obj_new_button) { + instance_destroy(); + } + with (obj_ingame_menu) { + instance_destroy(); + } // Other here - alarm[0]=1;onceh=1; + alarm[0] = 1; + onceh = 1; } + } } } diff --git a/objects/obj_saveload/Mouse_60.gml b/objects/obj_saveload/Mouse_60.gml index 387b296751..2d793b8414 100644 --- a/objects/obj_saveload/Mouse_60.gml +++ b/objects/obj_saveload/Mouse_60.gml @@ -2,14 +2,29 @@ if (slow<0) then slow=0; slow+=1; -if (slow>=3){ - if (top>1){top-=1; - if (sprite_exists(img4)){sprite_delete(img4);} - img4=img3;img3=img2;img2=img1; - if (file_exists(working_directory + "\\screen"+string(save[top])+".png")) then img1=sprite_add(working_directory + "\\screen"+string(save[top])+".png",1,0,0,0,0); - if (!sprite_exists(img3)) and (file_exists(working_directory + "\\screen"+string(save[top+2])+".png")) then img3=sprite_add(working_directory + "\\screen"+string(save[top+3])+".png",1,0,0,0,0); - if (!sprite_exists(img2)) and (file_exists(working_directory + "\\screen"+string(save[top+1])+".png")) then img2=sprite_add(working_directory + "\\screen"+string(save[top+2])+".png",1,0,0,0,0); - if (!sprite_exists(img1)) and (file_exists(working_directory + "\\screen"+string(save[top])+".png")) then img1=sprite_add(working_directory + "\\screen"+string(save[top])+".png",1,0,0,0,0); - } +if (slow >= 3) { + if (top > 1) { + top -= 1; + if (sprite_exists(img4)) { + sprite_delete(img4); + } + img4 = img3; + img3 = img2; + img2 = img1; + if (file_exists(string(PATH_save_previews, save[top]))) { + img1 = sprite_add(string(PATH_save_previews, save[top]), 1, 0, 0, 0, 0); + } + + if ((!sprite_exists(img3)) && file_exists(string(PATH_save_previews, save[top + 2]))) { + img3 = sprite_add(string(PATH_save_previews, save[top + 3]), 1, 0, 0, 0, 0); + } + + if ((!sprite_exists(img2)) && file_exists(string(PATH_save_previews, save[top + 1]))) { + img2 = sprite_add(string(PATH_save_previews, save[top + 2]), 1, 0, 0, 0, 0); + } + + if ((!sprite_exists(img1)) && file_exists(string(PATH_save_previews, save[top]))) { + img1 = sprite_add(string(PATH_save_previews, save[top]), 1, 0, 0, 0, 0); + } + } } - diff --git a/objects/obj_saveload/Mouse_61.gml b/objects/obj_saveload/Mouse_61.gml index d9f929549a..cf9aba8af7 100644 --- a/objects/obj_saveload/Mouse_61.gml +++ b/objects/obj_saveload/Mouse_61.gml @@ -9,10 +9,18 @@ if (slow<=-3){ if (sprite_exists(img4)){sprite_delete(img4);} - if (file_exists(working_directory + "\\screen"+string(save[top+3])+".png")) then img4=sprite_add(working_directory + "\\screen"+string(save[top+3])+".png",1,0,0,0,0); - if (!sprite_exists(img3)) and (file_exists(working_directory + "\\screen"+string(save[top+2])+".png")) then img3=sprite_add(working_directory + "\\screen"+string(save[top+2])+".png",1,0,0,0,0); - if (!sprite_exists(img2)) and (file_exists(working_directory + "\\screen"+string(save[top+1])+".png")) then img2=sprite_add(working_directory + "\\screen"+string(save[top+1])+".png",1,0,0,0,0); - if (!sprite_exists(img1)) and (file_exists(working_directory + "\\screen"+string(save[top])+".png")) then img1=sprite_add(working_directory + "\\screen"+string(save[top])+".png",1,0,0,0,0); + if (file_exists(string(PATH_save_previews, save[top + 3]))) { + img4 = sprite_add(string(PATH_save_previews, save[top + 3]), 1, 0, 0, 0, 0); + } + if ((!sprite_exists(img3)) && file_exists(string(PATH_save_previews, save[top + 2]))) { + img3 = sprite_add(string(PATH_save_previews, save[top + 2]), 1, 0, 0, 0, 0); + } + if ((!sprite_exists(img2)) && file_exists(string(PATH_save_previews, save[top + 1]))) { + img2 = sprite_add(string(PATH_save_previews, save[top + 1]), 1, 0, 0, 0, 0); + } + if ((!sprite_exists(img1)) && file_exists(string(PATH_save_previews, save[top]))) { + img1 = sprite_add(string(PATH_save_previews, save[top]), 1, 0, 0, 0, 0); + } diff --git a/scripts/__init_external/__init_external.gml b/scripts/__init_external/__init_external.gml index 72356b55f5..acba85bf39 100644 --- a/scripts/__init_external/__init_external.gml +++ b/scripts/__init_external/__init_external.gml @@ -21,7 +21,12 @@ function __init_external() { if (!directory_exists("Custom Files\\Custom Icons")) { directory_create("Custom Files\\Custom Icons"); } + if (!directory_exists("Save Files")) { + directory_create("Save Files"); + } + #macro PATH_save_files "Save Files\\save{0}.json" + #macro PATH_save_previews "Save Files\\screen{0}.png" #macro PATH_custom_icons $"Custom Files\\Custom Icons\\custom" #macro PATH_last_messages $"Logs/last_messages.log" diff --git a/scripts/scr_load/scr_load.gml b/scripts/scr_load/scr_load.gml index 0bf325fe2e..ba9176ebda 100644 --- a/scripts/scr_load/scr_load.gml +++ b/scripts/scr_load/scr_load.gml @@ -6,7 +6,7 @@ function load_marine_struct(company, marine, struct){ }; function scr_load(save_part, save_id) { - var filename = $"save{save_id}.json"; + var filename = string(PATH_save_files, save_id); if(file_exists(filename)){ var _gamesave_buffer = buffer_load(filename); var _gamesave_string = buffer_read(_gamesave_buffer, buffer_string); diff --git a/scripts/scr_save/scr_save.gml b/scripts/scr_save/scr_save.gml index 9366d9d826..b29bd43bb5 100644 --- a/scripts/scr_save/scr_save.gml +++ b/scripts/scr_save/scr_save.gml @@ -120,7 +120,7 @@ function scr_save(save_part,save_id) { var _gamesave_string = json_stringify(obj_saveload.GameSave, true); var _gamesave_buffer = buffer_create(string_byte_length(_gamesave_string) + 1, buffer_fixed, 1); - var filename = $"save{save_id}.json"; + var filename = string(PATH_save_files, save_id); buffer_write(_gamesave_buffer, buffer_string, _gamesave_string); buffer_save(_gamesave_buffer, filename); From b03742fac6b1b5f76b81a6e47e647ba61c86b565 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 05:13:14 +0300 Subject: [PATCH 06/12] Log the saving process and skip methods --- scripts/scr_save/scr_save.gml | 19 +++++++++++++++++-- .../scr_serialization_functions.gml | 10 +++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/scripts/scr_save/scr_save.gml b/scripts/scr_save/scr_save.gml index b29bd43bb5..9153abaa31 100644 --- a/scripts/scr_save/scr_save.gml +++ b/scripts/scr_save/scr_save.gml @@ -17,7 +17,9 @@ function ini_encode_and_json_advanced(ini_area, ini_code, value){ function scr_save(save_part,save_id) { var t1 = get_timer(); try{ + log_message($"Saving to slot {save_id} - started!"); if (save_part=1) or (save_part=0){ + log_message($"Saving to slot {save_id} - part {save_part} started!"); var t=date_current_datetime(); var month=date_get_month(t); var day=date_get_day(t); @@ -28,6 +30,7 @@ function scr_save(save_part,save_id) { if (hour=0) then hour=12; var mahg=minute; if (mahg<10) then minute=$"0{mahg}"; + log_message($"Saving to slot {save_id} - vars are assigned!"); obj_saveload.GameSave.Save = { chapter_name: global.chapter_name, @@ -49,6 +52,7 @@ function scr_save(save_part,save_id) { en_fleets: instance_number(obj_en_fleet), sod: random_get_seed(), } + log_message($"Saving to slot {save_id} - GameSave struct created!"); /// STARS var num=instance_number(obj_star); @@ -57,10 +61,12 @@ function scr_save(save_part,save_id) { var star_json = star_obj.serialize(); array_push(obj_saveload.GameSave.Stars, star_json); } + log_message($"Saving to slot {save_id} - stars are serialized and stored!"); } if (save_part=2) or (save_part=0){ + log_message($"Saving to slot {save_id} - part {save_part} started!"); // PLAYER FLEET OBJECTS var num = instance_number(obj_p_fleet); for (var i=0; i"; - log_warning($"Bad array save: '{_field_name}' internal type found was not a simple type and should probably have it's own serialize function - {_source_obj_name}"); + log_warning($"Bad array save: '{_field_name}' internal type found was not a simple type and should probably have it's own serialize function - {_source_obj_name}!"); } else { variable_struct_set(_destination, _field_name, _field_value); } } else if (is_struct(_field_value) && !struct_exists(_destination, _field_name)) { var _source_obj_name = struct_exists(_source, "object_index") ? object_get_name(_source.object_index) : ""; - log_warning($"obj_ini.serialze() - {_source_obj_name} - object contains struct variable '{_field_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning"); + log_warning($"obj_ini.serialze() - {_source_obj_name} - object contains struct variable '{_field_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning!"); } } } From 863e7a00c5498192158c7b32d8d21cd6d6bf40ae Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:04:23 +0300 Subject: [PATCH 07/12] Loading timer; both timers in seconds --- scripts/scr_load/scr_load.gml | 5 ++++- scripts/scr_save/scr_save.gml | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/scr_load/scr_load.gml b/scripts/scr_load/scr_load.gml index ba9176ebda..322d523f2e 100644 --- a/scripts/scr_load/scr_load.gml +++ b/scripts/scr_load/scr_load.gml @@ -6,6 +6,7 @@ function load_marine_struct(company, marine, struct){ }; function scr_load(save_part, save_id) { + var t1 = get_timer(); var filename = string(PATH_save_files, save_id); if(file_exists(filename)){ var _gamesave_buffer = buffer_load(filename); @@ -145,5 +146,7 @@ function scr_load(save_part, save_id) { // room_goto(Game); } - + var t2 = get_timer(); + var diff = (t2 - t1) / 1000000; + log_message($"Loading part {save_part} took {diff} seconds!"); } diff --git a/scripts/scr_save/scr_save.gml b/scripts/scr_save/scr_save.gml index 9153abaa31..0a3e62f089 100644 --- a/scripts/scr_save/scr_save.gml +++ b/scripts/scr_save/scr_save.gml @@ -148,7 +148,6 @@ function scr_save(save_part,save_id) { } var t2 = get_timer(); - - var diff = t2 - t1; - log_message($"scr_save save_part {save_part} took {diff} microseconds"); + var diff = (t2 - t1) / 1000000; + log_message($"Saving part {save_part} took {diff} seconds!"); } From 72360bd3b3f994d57bf9d83b8efeae2642cda1fd Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:05:07 +0300 Subject: [PATCH 08/12] Pre-create TTRPG array, as it has to be fixed size --- objects/obj_ini/Create_0.gml | 1 + 1 file changed, 1 insertion(+) diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 49b2937cfe..28f0479e82 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -209,6 +209,7 @@ deserialize = function(save_data){ } if(struct_exists(save_data, "marine_structs")){ + obj_ini.TTRPG = array_create(11, []); var marines_encoded_arr = save_data.marine_structs; var _m_ar_len = array_length(marines_encoded_arr); for(var m = 0; m < _m_ar_len; m++){ From 41e3ea2f12ee193a83dbac8ac4e399c866cd65f4 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:23:26 +0300 Subject: [PATCH 09/12] Don't check bool --- .../scr_general_variable_functions.gml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/scr_general_variable_functions/scr_general_variable_functions.gml b/scripts/scr_general_variable_functions/scr_general_variable_functions.gml index def81cb8cc..10d2c15fab 100644 --- a/scripts/scr_general_variable_functions/scr_general_variable_functions.gml +++ b/scripts/scr_general_variable_functions/scr_general_variable_functions.gml @@ -1,4 +1,4 @@ /// @description Checks if a variable is a simple data type (number, string, or boolean). function is_basic_variable(_variable) { - return is_numeric(_variable) || is_string(_variable) || is_bool(_variable); + return is_numeric(_variable) || is_string(_variable); } From bcd6f9f7e9a9fc9c22957349cc753891b8cfaa13 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:28:07 +0300 Subject: [PATCH 10/12] Don't stringify stuff separately from the rest of save data --- objects/obj_star/Create_0.gml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index bce5dacdff..fc9661bf67 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -139,14 +139,14 @@ serialize = function(){ obj: object_get_name(object_index), x, y, - present_fleet: json_stringify(object_star.present_fleet, true), + present_fleet: object_star.present_fleet, planet_data: planet_data, } if(struct_exists(object_star, "system_garrison")){ - save_data.system_garrison = json_stringify(object_star.system_garrison, true); + save_data.system_garrison = object_star.system_garrison; } if(struct_exists(object_star, "system_sabatours")){ - save_data.system_sabatours = json_stringify(object_star.system_sabatours, true); + save_data.system_sabatours = object_star.system_sabatours; } @@ -175,7 +175,7 @@ function deserialize(save_data){ // Set explicit vars here if(struct_exists(save_data, "present_fleet")){ - variable_struct_set(self, "present_fleet", json_parse(save_data.present_fleet)); + variable_struct_set(self, "present_fleet", save_data.present_fleet); } if(struct_exists(save_data, "planet_data")){ @@ -198,10 +198,10 @@ function deserialize(save_data){ } if(struct_exists(save_data, "system_sabatours")){ - variable_struct_set(self, "system_sabatours", json_parse(save_data.system_sabatours)); + variable_struct_set(self, "system_sabatours", save_data.system_sabatours); } if(struct_exists(save_data, "system_garrison")){ - variable_struct_set(self, "system_garrison", json_parse(save_data.system_garrison)); + variable_struct_set(self, "system_garrison", save_data.system_garrison); } } From 91006755250f2a0cf5aef829ece6b1782abbace4 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 09:32:20 +0300 Subject: [PATCH 11/12] Save the point_breakdown struct (not sure if needed tho) --- objects/obj_p_fleet/Create_0.gml | 1 + 1 file changed, 1 insertion(+) diff --git a/objects/obj_p_fleet/Create_0.gml b/objects/obj_p_fleet/Create_0.gml index d7f3e2e404..e0d27e540d 100644 --- a/objects/obj_p_fleet/Create_0.gml +++ b/objects/obj_p_fleet/Create_0.gml @@ -66,6 +66,7 @@ serialize = function(){ obj: object_get_name(object_index), x, y, + point_breakdown: point_breakdown } var excluded_from_save = ["temp", "serialize", "deserialize"] From b9792ca25dc9b4eac5ee46dabef263541e682f69 Mon Sep 17 00:00:00 2001 From: EttyKitty <20323032+EttyKitty@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:42:39 +0300 Subject: [PATCH 12/12] More continue, for consistency Just so the whole function looks the same --- .../scr_serialization_functions.gml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/scr_serialization_functions/scr_serialization_functions.gml b/scripts/scr_serialization_functions/scr_serialization_functions.gml index fc8d8efa7e..cab00ec0ef 100644 --- a/scripts/scr_serialization_functions/scr_serialization_functions.gml +++ b/scripts/scr_serialization_functions/scr_serialization_functions.gml @@ -34,6 +34,7 @@ function copy_serializable_fields(_source, _destination, _exclude = [], _exclude if (is_basic_variable(_field_value)) { variable_struct_set(_destination, _field_name, _field_value); + continue; } if (is_array(_field_value)) { @@ -43,9 +44,13 @@ function copy_serializable_fields(_source, _destination, _exclude = [], _exclude } else { variable_struct_set(_destination, _field_name, _field_value); } - } else if (is_struct(_field_value) && !struct_exists(_destination, _field_name)) { + continue; + } + + if (is_struct(_field_value) && !struct_exists(_destination, _field_name)) { var _source_obj_name = struct_exists(_source, "object_index") ? object_get_name(_source.object_index) : ""; log_warning($"obj_ini.serialze() - {_source_obj_name} - object contains struct variable '{_field_name}' which has not been serialized. \n\tEnsure that serialization is written into the serialize and deserialization function if it is needed for this value, or that the variable is added to the ignore list to suppress this warning!"); + continue; } } }