Files
puzzle-quest/scripts/Database.gd
T

149 lines
3.8 KiB
GDScript
Raw Normal View History

2021-06-03 22:18:50 +02:00
extends Node
# Lightweight replacement for the godot_db_manager plugin (incompatible with
# Godot 4). Keeps the ahog.json format used by the rest of the project and
# exposes the same surface API the M* model classes expect:
#
# Global.database.get_table_by_name(name) -> Table
# Global.database.save_db()
# table.get_data_at_row_idx(row_id) -> [Cell, Cell, ...]
# table.edit_data(prop_id, row_id, value)
# table.m_rows_count
# table.get_data_by_prop_name_and_data(prop_name, value) -> Array
# table.get_dictionary_by_prop_name_and_data(prop_name, value) -> Array[Dict]
# cell.get_data() -> String
class Cell:
var _value
func _init(value):
_value = value
func get_data():
return _value
class Table:
var name: String
var props: Array
var data: Array
var m_rows_count: int
func _init(table_dict: Dictionary):
name = table_dict["table_name"]
props = table_dict["props"]
data = table_dict["data"]
m_rows_count = data.size() / max(1, props.size())
func _col_count() -> int:
return props.size()
func _find_prop_idx(prop_name: String) -> int:
for i in range(props.size()):
if props[i]["name"] == prop_name:
return i
return -1
func get_data_at_row_idx(row_idx: int) -> Array:
var start = row_idx * _col_count()
var cells = []
for i in range(_col_count()):
cells.append(Cell.new(data[start + i]))
return cells
func edit_data(prop_id: int, row_id: int, value) -> void:
data[row_id * _col_count() + prop_id] = str(value)
func get_data_by_prop_name_and_data(prop_name: String, value) -> Array:
var prop_idx = _find_prop_idx(prop_name)
var matches = []
if prop_idx == -1:
return matches
for row in range(m_rows_count):
if data[row * _col_count() + prop_idx] == str(value):
matches.append(row)
return matches
func get_dictionary_by_prop_name_and_data(prop_name: String, value) -> Array:
var prop_idx = _find_prop_idx(prop_name)
var results = []
if prop_idx == -1:
return results
for row in range(m_rows_count):
if data[row * _col_count() + prop_idx] == str(value):
var d = {}
for i in range(_col_count()):
d[props[i]["name"]] = data[row * _col_count() + i]
results.append(d)
return results
func to_dict() -> Dictionary:
return {
"table_name": name,
"props": props,
"data": data,
}
class DB:
var version: String
var db_name: String
var tables: Dictionary = {}
var _path: String
func _init(path: String):
_path = path
var f = FileAccess.open(path, FileAccess.READ)
if f == null:
push_error("[Database] Cannot open " + path)
return
var raw = f.get_as_text()
f.close()
var doc = JSON.parse_string(raw)
if doc == null:
push_error("[Database] Invalid JSON in " + path)
return
version = doc.get("GDDB_ver", "")
db_name = doc.get("db_name", "")
for t in doc.get("tables", []):
var table = Table.new(t)
tables[table.name] = table
func get_table_by_name(name: String):
return tables.get(name)
func save_db() -> void:
var doc = {
"GDDB_ver": version,
"db_name": db_name,
"tables": [],
}
for tname in tables:
doc["tables"].append(tables[tname].to_dict())
var f = FileAccess.open(_path, FileAccess.WRITE)
if f == null:
push_error("[Database] Cannot write " + _path)
return
f.store_string(JSON.stringify(doc))
f.close()
func initialize() -> DB:
return DB.new(save_database_in())
func save_database_in() -> String:
2021-06-06 18:54:25 +02:00
if OS.get_name() == "Android":
copy_database()
return android_path()
return normal_path()
2021-06-06 18:54:25 +02:00
func android_path() -> String:
2021-06-06 18:54:25 +02:00
return "user://database.json"
func normal_path() -> String:
2021-06-06 18:54:25 +02:00
return "res://db/ahog.json"
func copy_database() -> void:
if FileAccess.file_exists(android_path()):
return
var src = FileAccess.open(normal_path(), FileAccess.READ)
var dst = FileAccess.open(android_path(), FileAccess.WRITE)
dst.store_string(src.get_as_text())
dst.close()
src.close()