2024-08-01 13:33:58 +00:00
|
|
|
class_name DataHandler
|
|
|
|
|
2024-11-26 12:58:42 +00:00
|
|
|
extends Node
|
|
|
|
|
2024-08-30 09:51:08 +00:00
|
|
|
var data_file_path = "/app/retrodeck/config/retrodeck/reference_lists/features.json"
|
2024-08-01 13:33:58 +00:00
|
|
|
var app_data: AppData
|
|
|
|
|
|
|
|
func _ready():
|
|
|
|
# Load the data when the scene is ready
|
2024-08-04 18:45:51 +00:00
|
|
|
app_data = load_base_data()
|
2024-08-01 13:33:58 +00:00
|
|
|
|
2024-08-04 18:45:51 +00:00
|
|
|
func load_base_data() -> AppData:
|
2024-08-01 13:33:58 +00:00
|
|
|
var file = FileAccess.open(data_file_path, FileAccess.READ)
|
|
|
|
if file:
|
|
|
|
var json_data = file.get_as_text()
|
|
|
|
file.close()
|
2024-08-20 20:57:49 +00:00
|
|
|
#var json = JSON.new()
|
|
|
|
var parsed_data = JSON.parse_string(json_data)
|
2024-08-01 16:03:20 +00:00
|
|
|
if parsed_data:
|
|
|
|
var data_dict = parsed_data
|
2024-08-01 13:33:58 +00:00
|
|
|
var about_links = {}
|
|
|
|
for key in data_dict["about_links"].keys():
|
|
|
|
var link_data = data_dict["about_links"][key]
|
|
|
|
var link = Link.new()
|
|
|
|
link.name = link_data["name"]
|
|
|
|
link.url = link_data["url"]
|
|
|
|
link.description = link_data["description"]
|
2024-08-20 20:57:49 +00:00
|
|
|
link.icon = link_data["icon"]
|
2024-08-01 13:33:58 +00:00
|
|
|
about_links[key] = link
|
|
|
|
|
|
|
|
var emulators = {}
|
2024-08-14 22:15:10 +00:00
|
|
|
for key in data_dict["emulator"].keys():
|
|
|
|
var emulator_data = data_dict["emulator"][key]
|
2024-08-24 16:48:06 +00:00
|
|
|
var emulator = Emulator.new()
|
2024-08-01 13:33:58 +00:00
|
|
|
emulator.name = emulator_data["name"]
|
|
|
|
emulator.description = emulator_data["description"]
|
2024-11-27 12:59:38 +00:00
|
|
|
if emulator_data.has("url"):
|
|
|
|
emulator.url = emulator_data["url"]
|
|
|
|
if emulator_data.has("system"):
|
2024-11-27 19:31:31 +00:00
|
|
|
emulator.system = str(emulator_data["system"])
|
2024-08-27 15:57:12 +00:00
|
|
|
emulator.launch = emulator_data["launch"]
|
2024-08-14 22:15:10 +00:00
|
|
|
if emulator_data.has("properties"):
|
|
|
|
for property_data in emulator_data["properties"]:
|
2024-08-24 20:52:27 +00:00
|
|
|
#print (emulator,"----",property_data)
|
2024-08-24 16:48:06 +00:00
|
|
|
var property = EmulatorProperty.new()
|
2024-08-18 21:42:40 +00:00
|
|
|
if property_data.has("cheevos"):
|
|
|
|
property.cheevos = property_data.get("cheevos",true)
|
|
|
|
if property_data.has("cheevos_hardcore"):
|
|
|
|
property.cheevos_hardcore = property_data.get("cheevos_hardcore",true)
|
|
|
|
if property_data.has("abxy_button"):
|
|
|
|
property.abxy_button = property_data.get("abxy_button",true)
|
|
|
|
if property_data.has("multi_user_config_dir"):
|
|
|
|
property.multi_user_config_dir = property_data.get("multi_user_config_dir",true)
|
2024-08-14 22:15:10 +00:00
|
|
|
emulator.properties.append(property)
|
2024-08-01 13:33:58 +00:00
|
|
|
emulators[key] = emulator
|
2024-08-27 15:57:12 +00:00
|
|
|
#TODO add systems too
|
2024-08-25 07:03:25 +00:00
|
|
|
var cores = {}
|
|
|
|
for key in data_dict["emulator"]["retroarch"]["cores"].keys():
|
|
|
|
var core_data = data_dict["emulator"]["retroarch"]["cores"][key]
|
|
|
|
var core = Core.new()
|
2024-08-24 17:47:51 +00:00
|
|
|
core.name = core_data["name"]
|
|
|
|
core.description = core_data["description"]
|
|
|
|
if core_data.has("properties"):
|
|
|
|
for property_data in core_data["properties"]:
|
2024-08-24 20:52:27 +00:00
|
|
|
#print (core.name,"----",property_data)
|
2024-09-11 18:23:05 +00:00
|
|
|
# inherit from RetroArch
|
2024-08-24 20:52:27 +00:00
|
|
|
var property = CoreProperty.new()
|
2024-08-24 17:47:51 +00:00
|
|
|
property.cheevos = true
|
|
|
|
property.cheevos_hardcore = true
|
|
|
|
property.quick_resume = true
|
2024-08-24 20:52:27 +00:00
|
|
|
if property_data.has("abxy_button"):
|
|
|
|
property.abxy_button = property_data.get("abxy_button",true)
|
|
|
|
if property_data.has("widescreen"):
|
|
|
|
property.widescreen = property_data.get("widescreen",true)
|
|
|
|
if property_data.has("borders"):
|
|
|
|
property.borders = property_data.get("borders",true)
|
|
|
|
if property_data.has("rewind"):
|
|
|
|
property.rewind = property_data.get("rewind",true)
|
|
|
|
core.properties.append(property)
|
2024-08-25 07:03:25 +00:00
|
|
|
cores[key] = core
|
|
|
|
|
2024-08-20 20:57:49 +00:00
|
|
|
var app_dict = AppData.new()
|
|
|
|
app_dict.about_links = about_links
|
|
|
|
app_dict.emulators = emulators
|
2024-08-25 07:03:25 +00:00
|
|
|
app_dict.cores = cores
|
2024-08-20 20:57:49 +00:00
|
|
|
return app_dict
|
2024-08-01 13:33:58 +00:00
|
|
|
else:
|
2024-09-13 10:07:59 +00:00
|
|
|
class_functions.logger("d","Error parsing JSON ")
|
2024-08-01 13:33:58 +00:00
|
|
|
else:
|
2024-10-09 11:00:24 +00:00
|
|
|
class_functions.logger("d","Error opening file: %s" % file)
|
2024-08-21 03:22:17 +00:00
|
|
|
get_tree().quit()
|
2024-08-01 13:33:58 +00:00
|
|
|
return null
|
|
|
|
|
2024-08-27 20:05:59 +00:00
|
|
|
func save_base_data(app_dict: AppData):
|
2024-08-01 16:03:20 +00:00
|
|
|
var file = FileAccess.open(data_file_path, FileAccess.READ)
|
|
|
|
var existing_data = {}
|
2024-08-01 13:33:58 +00:00
|
|
|
if file:
|
2024-08-01 16:03:20 +00:00
|
|
|
var json = JSON.new()
|
|
|
|
var error = json.parse(file.get_as_text())
|
|
|
|
if error == OK:
|
|
|
|
existing_data = json.get_data()
|
|
|
|
file.close()
|
|
|
|
else:
|
|
|
|
print("File not found. Creating a new one.")
|
2024-08-29 16:37:17 +00:00
|
|
|
#var about_links ={}
|
|
|
|
var about_links_new = Link.new()
|
2024-08-20 20:57:49 +00:00
|
|
|
for key in app_dict.about_links.keys():
|
|
|
|
var link = app_dict.about_links[key]
|
2024-08-29 16:37:17 +00:00
|
|
|
about_links_new[key] = {
|
2024-08-01 13:33:58 +00:00
|
|
|
"name": link.name,
|
|
|
|
"url": link.url,
|
|
|
|
"description": link.description
|
|
|
|
}
|
2024-08-01 16:03:20 +00:00
|
|
|
var new_data_dict = {}
|
2024-08-29 16:37:17 +00:00
|
|
|
#var about_links = {}
|
|
|
|
var about_links = Link.new()
|
2024-08-20 20:57:49 +00:00
|
|
|
for key in app_dict.about_links.keys():
|
|
|
|
var link = app_dict.about_links[key]
|
2024-08-01 16:03:20 +00:00
|
|
|
about_links[key] = {
|
|
|
|
"name": link.name,
|
|
|
|
"url": link.url,
|
|
|
|
"description": link.description
|
|
|
|
}
|
|
|
|
var emulators = {}
|
2024-08-20 20:57:49 +00:00
|
|
|
for key in app_dict.emulators.keys():
|
2024-08-01 16:03:20 +00:00
|
|
|
var emulator = app_data.emulators[key]
|
|
|
|
var properties = []
|
|
|
|
for property in emulator.properties:
|
|
|
|
properties.append({
|
2024-08-18 21:42:40 +00:00
|
|
|
#"standalone": property.standalone,
|
2024-08-20 20:57:49 +00:00
|
|
|
"abxy_button": {"status": property.abxy_button}
|
2024-08-01 16:03:20 +00:00
|
|
|
})
|
|
|
|
emulators[key] = {
|
|
|
|
"name": emulator.name,
|
|
|
|
"description": emulator.description,
|
2024-08-27 20:05:59 +00:00
|
|
|
"launch": emulator.launch,
|
2024-09-05 14:11:02 +00:00
|
|
|
"system": emulator.system,
|
2024-08-27 20:05:59 +00:00
|
|
|
"url": emulator.url,
|
2024-08-01 16:03:20 +00:00
|
|
|
"properties": properties
|
|
|
|
}
|
|
|
|
new_data_dict["about_links"] = about_links
|
|
|
|
new_data_dict["emulators"] = emulators
|
|
|
|
# Merge existing data with new data
|
|
|
|
for key in new_data_dict.keys():
|
|
|
|
if existing_data.has(key):
|
|
|
|
var existing_dict = existing_data[key]
|
|
|
|
var new_dict = new_data_dict[key]
|
|
|
|
|
|
|
|
# Merge dictionaries
|
|
|
|
for sub_key in new_dict.keys():
|
|
|
|
existing_dict[sub_key] = new_dict[sub_key]
|
|
|
|
else:
|
|
|
|
existing_data[key] = new_data_dict[key]
|
|
|
|
# Serialize the combined data to JSON
|
2024-08-20 20:57:49 +00:00
|
|
|
#var json_text = JSON.new().stringify(existing_data, "\t")
|
|
|
|
#var json_text = json.stringify(existing_data, "\t")
|
|
|
|
var json_text = JSON.stringify(existing_data, "\t")
|
2024-08-01 16:03:20 +00:00
|
|
|
|
|
|
|
# Open the file in append mode and write the new JSON data
|
|
|
|
file = FileAccess.open(data_file_path, FileAccess.WRITE)
|
|
|
|
file.store_string(json_text)
|
|
|
|
file.close()
|
2024-08-04 18:45:51 +00:00
|
|
|
|
|
|
|
func parse_config_to_json(file_path: String) -> Dictionary:
|
|
|
|
var config = {}
|
|
|
|
var current_section = ""
|
|
|
|
var file = FileAccess.open(file_path, FileAccess.READ)
|
|
|
|
if file == null:
|
2024-09-13 10:07:59 +00:00
|
|
|
class_functions.logger("e","Failed to open file: " + file_path)
|
2024-08-04 18:45:51 +00:00
|
|
|
return config
|
|
|
|
while not file.eof_reached():
|
|
|
|
var line = file.get_line().strip_edges()
|
|
|
|
if line.begins_with("[") and line.ends_with("]"):
|
|
|
|
current_section = line.substr(1, line.length() - 2)
|
|
|
|
config[current_section] = {}
|
|
|
|
elif line != "" and not line.begins_with("#"):
|
|
|
|
var parts = line.split("=")
|
|
|
|
if parts.size() == 2:
|
|
|
|
var key = parts[0].strip_edges()
|
2024-09-05 14:11:02 +00:00
|
|
|
var value = parts[1].strip_edges()
|
2024-08-04 18:45:51 +00:00
|
|
|
if value == "true":
|
|
|
|
value = true
|
|
|
|
elif value == "false":
|
|
|
|
value = false
|
|
|
|
if key == "version":
|
|
|
|
config[key] = value
|
|
|
|
else:
|
|
|
|
if current_section == "":
|
|
|
|
config[key] = value
|
|
|
|
else:
|
|
|
|
config[current_section][key] = value
|
|
|
|
file.close()
|
|
|
|
return config
|
|
|
|
|
|
|
|
func config_save_json(config: Dictionary, json_file_path: String) -> void:
|
2024-08-20 20:57:49 +00:00
|
|
|
#var json = JSON.new()
|
|
|
|
var json_string = JSON.stringify(config, "\t")
|
2024-08-04 18:45:51 +00:00
|
|
|
|
|
|
|
var file = FileAccess.open(json_file_path, FileAccess.WRITE)
|
|
|
|
if file != null:
|
|
|
|
file.store_string(json_string)
|
|
|
|
file.close()
|
|
|
|
else:
|
2024-09-12 15:29:10 +00:00
|
|
|
class_functions.logger("e", "File not found: %s" % json_file_path)
|
|
|
|
|
|
|
|
func read_cfg_file(file_path: String) -> Array:
|
|
|
|
var lines: Array = []
|
|
|
|
var file: FileAccess = FileAccess.open(file_path, FileAccess.ModeFlags.READ)
|
|
|
|
if file:
|
|
|
|
while not file.eof_reached():
|
|
|
|
var line: String = file.get_line()
|
|
|
|
lines.append(line)
|
|
|
|
file.close()
|
|
|
|
else:
|
|
|
|
class_functions.logger("e", "File not found: %s" % file_path)
|
|
|
|
return lines
|
|
|
|
|
|
|
|
func write_cfg_file(file_path: String, lines: Array, changes: Dictionary) -> void:
|
|
|
|
var file: FileAccess = FileAccess.open(file_path, FileAccess.ModeFlags.WRITE)
|
|
|
|
var current_section: String = ""
|
2024-09-16 15:38:41 +00:00
|
|
|
var line_count: int = lines.size()
|
|
|
|
for i in line_count:
|
|
|
|
var line: String = lines[i]
|
2024-09-12 15:29:10 +00:00
|
|
|
var trimmed_line: String = line.strip_edges()
|
|
|
|
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
|
2024-09-16 15:38:41 +00:00
|
|
|
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")# trimmed_line.trim_prefix("["].trim_suffix("]")
|
2024-09-12 15:29:10 +00:00
|
|
|
file.store_line(line)
|
|
|
|
elif "=" in trimmed_line and current_section in changes:
|
|
|
|
var parts: Array = trimmed_line.split("=", false)
|
2024-09-16 15:38:41 +00:00
|
|
|
if parts.size() == 2:
|
2024-09-12 15:29:10 +00:00
|
|
|
var key: String = parts[0].strip_edges()
|
|
|
|
var original_value: String = parts[1].strip_edges()
|
|
|
|
if key in changes[current_section]:
|
|
|
|
var new_value: String = changes[current_section][key]
|
|
|
|
if new_value != original_value:
|
2024-09-16 15:38:41 +00:00
|
|
|
file.store_line("%s=%s" % [key, new_value])
|
|
|
|
class_functions.logger("i", "Changed %s in section [%s] from %s to %s" % [key, current_section, original_value, new_value])
|
2024-09-12 15:29:10 +00:00
|
|
|
else:
|
|
|
|
file.store_line(line)
|
|
|
|
else:
|
|
|
|
file.store_line(line)
|
|
|
|
else:
|
|
|
|
file.store_line(line)
|
|
|
|
else:
|
|
|
|
file.store_line(line)
|
2024-09-16 15:38:41 +00:00
|
|
|
if i == line_count - 2:
|
|
|
|
break
|
2024-09-12 15:29:10 +00:00
|
|
|
file.close()
|
|
|
|
|
2024-09-15 18:18:48 +00:00
|
|
|
func change_cfg_value(file_path: String, system: String, section: String, new_value: String) -> Array:
|
2024-09-12 15:29:10 +00:00
|
|
|
var lines: Array = read_cfg_file(file_path)
|
2024-09-15 18:18:48 +00:00
|
|
|
var parameters: Array =[system, section]
|
2024-09-12 15:29:10 +00:00
|
|
|
var changes: Dictionary = {}
|
2024-09-16 15:38:41 +00:00
|
|
|
changes[section] = {system: new_value}
|
|
|
|
class_functions.logger("i", "Change: System: %s Section %s New Value: %s" % [system, section, new_value])
|
2024-09-12 15:29:10 +00:00
|
|
|
write_cfg_file(file_path, lines, changes)
|
2024-09-12 15:48:16 +00:00
|
|
|
return parameters
|
2024-09-13 17:27:07 +00:00
|
|
|
|
2024-09-15 18:18:48 +00:00
|
|
|
func change_all_cfg_values(file_path: String, systems: Dictionary, section: String, new_value: String) -> Array:
|
2024-09-13 17:27:07 +00:00
|
|
|
var lines: Array = read_cfg_file(file_path)
|
2024-09-15 18:18:48 +00:00
|
|
|
var parameters: Array =[systems, section]
|
2024-09-13 17:27:07 +00:00
|
|
|
var changes: Dictionary = {}
|
|
|
|
var current_section: String
|
|
|
|
for line in lines:
|
|
|
|
var trimmed_line: String = line.strip_edges()
|
|
|
|
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
|
|
|
|
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")
|
|
|
|
if current_section == section:
|
2024-09-15 18:18:48 +00:00
|
|
|
changes[current_section] = {}
|
2024-09-13 17:27:07 +00:00
|
|
|
elif "=" in trimmed_line and current_section == section:
|
|
|
|
var parts: Array = trimmed_line.split("=", false)
|
|
|
|
if parts.size() >= 2:
|
|
|
|
var key: String = parts[0].strip_edges()
|
|
|
|
changes[section][key] = new_value
|
2024-09-15 18:18:48 +00:00
|
|
|
class_functions.logger("i", "Change: Systems: %s Section %s New Value: %s" % [systems, section, new_value])
|
2024-09-13 17:27:07 +00:00
|
|
|
write_cfg_file(file_path, lines, changes)
|
|
|
|
return parameters
|
|
|
|
|
|
|
|
func get_elements_in_section(file_path: String, section: String) -> Dictionary:
|
|
|
|
var lines: Array = read_cfg_file(file_path)
|
|
|
|
var elements: Dictionary = {}
|
|
|
|
var current_section: String = ""
|
|
|
|
for line in lines:
|
|
|
|
var trimmed_line: String = line.strip_edges()
|
|
|
|
if trimmed_line.begins_with("[") and trimmed_line.ends_with("]"):
|
|
|
|
current_section = trimmed_line.trim_prefix("[").trim_suffix("]")
|
|
|
|
elif "=" in trimmed_line and current_section == section:
|
|
|
|
var parts: Array = trimmed_line.split("=", false)
|
|
|
|
if parts.size() >= 2:
|
|
|
|
var key: String = parts[0].strip_edges()
|
|
|
|
var value: String = parts[1].strip_edges()
|
|
|
|
elements[key] = value
|
|
|
|
return elements
|
2024-09-28 17:38:15 +00:00
|
|
|
|
2024-09-28 18:00:32 +00:00
|
|
|
func read_change_regex(file_path: String, key: String, new_value: String, use_quotes: bool = true) -> String:
|
2024-09-28 17:38:15 +00:00
|
|
|
var file := FileAccess.open(file_path, FileAccess.READ_WRITE)
|
|
|
|
if file == null:
|
|
|
|
print("Error: Could not open the file - %s" % file_path)
|
2024-09-28 18:00:32 +00:00
|
|
|
return ""
|
2024-09-28 17:38:15 +00:00
|
|
|
var content := file.get_as_text()
|
|
|
|
file.close()
|
|
|
|
var pattern := ""
|
|
|
|
if use_quotes:
|
|
|
|
pattern = '%s\\s*=\\s*"(.*?)"' % key
|
|
|
|
else:
|
|
|
|
pattern = '%s\\s*=\\s*(.*)' % key # For keys without quotes
|
|
|
|
var regex := RegEx.new()
|
|
|
|
regex.compile(pattern)
|
2024-09-28 18:00:32 +00:00
|
|
|
var match := regex.search(content)
|
|
|
|
if match == null:
|
|
|
|
print("Key %s not found for match - %s" % [key, match])
|
|
|
|
return ""
|
|
|
|
var current_value := match.get_string(1)
|
|
|
|
if new_value == current_value:
|
|
|
|
print (current_value)
|
|
|
|
return current_value
|
2024-09-28 17:38:15 +00:00
|
|
|
var updated_content := ""
|
|
|
|
if use_quotes:
|
|
|
|
updated_content = regex.sub(content, '%s = "%s"' % [key, new_value])
|
|
|
|
else:
|
|
|
|
updated_content = regex.sub(content, '%s = %s' % [key, new_value])
|
|
|
|
file = FileAccess.open(file_path, FileAccess.WRITE)
|
|
|
|
file.store_string(updated_content)
|
|
|
|
file.close()
|
|
|
|
print("File updated successfully")
|
2024-10-02 12:09:31 +00:00
|
|
|
return new_value
|