ec906117bb
godot_db_manager was incompatible with Godot 4 (used WindowDialog, Tabs, PopupPanel which were all removed). Replace with a minimal Database.gd that parses the same ahog.json format and exposes the same surface API (get_table_by_name, get_data_at_row_idx, edit_data, save_db, etc.) used by the M* model classes — no changes needed in MBase/MScene/MLevel/MSetting. Also port the lod plugin: fix class_name syntax (Godot 4 uses @icon separately from class_name extends) and Particles -> GPUParticles3D. Rewrite Global.gd async scene loading: the convert-3to4 tool mapped load_interactive -> load_threaded_request but those have different APIs (stage count, poll vs. status enum). Reimplement using the new load_threaded_get_status / load_threaded_get pair. Clean project.godot: drop the old _global_script_classes table (Godot 4 uses inline class_name declarations), remove gddb_* autoloads, and remove the godot_db_manager entry from editor_plugins. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
149 lines
3.8 KiB
GDScript
149 lines
3.8 KiB
GDScript
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:
|
|
if OS.get_name() == "Android":
|
|
copy_database()
|
|
return android_path()
|
|
return normal_path()
|
|
|
|
func android_path() -> String:
|
|
return "user://database.json"
|
|
|
|
func normal_path() -> String:
|
|
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()
|