238fccef95
- Global.gd: move @onready var animation below the regular vars
(gdlint class-definitions-order expects onready vars after
public/private vars).
- Database.gd::DB: move the three _*_PROPS constants above the vars
(constants come before vars in a class body).
- Levels.gd:_search_button_to_use: drop the elif after a branch
that returns (no-elif-return).
- Levels.gd:_gyroscope_changed_{down,up}: continuation lines of the
multi-line return mixed two tabs + three spaces; normalised to
pure tabs.
No semantic change: @onready is property-level so source ordering
doesn't affect init; elif after a return is equivalent to if; the
continuation indent is cosmetic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
178 lines
5.1 KiB
GDScript
178 lines
5.1 KiB
GDScript
extends Node
|
|
|
|
# Loads ahog.json once into typed Resource arrays:
|
|
# Global.database.settings -> SettingsData
|
|
# Global.database.levels -> Array[LevelEntry]
|
|
# Global.database.scenes -> Array[SceneEntry]
|
|
#
|
|
# save() round-trips back to the same JSON format so game progress
|
|
# (per-scene lock state) persists across runs.
|
|
|
|
class DB extends RefCounted:
|
|
const _SETTINGS_PROPS := [
|
|
{"name": "langue", "type": "1", "auto_increment": "0"},
|
|
{"name": "gyroscope", "type": "0", "auto_increment": "0"},
|
|
{"name": "ambient_sound", "type": "0", "auto_increment": "0"},
|
|
{"name": "resolution", "type": "3", "auto_increment": "0"},
|
|
{"name": "fullscreen", "type": "0", "auto_increment": "0"},
|
|
{"name": "version", "type": "0", "auto_increment": "0"},
|
|
]
|
|
const _LEVELS_PROPS := [
|
|
{"name": "name", "type": "3", "auto_increment": "0"},
|
|
{"name": "thumb", "type": "4", "auto_increment": "0"},
|
|
]
|
|
const _SCENES_PROPS := [
|
|
{"name": "lock", "type": "0", "auto_increment": "0"},
|
|
{"name": "label", "type": "3", "auto_increment": "0"},
|
|
{"name": "key", "type": "3", "auto_increment": "0"},
|
|
{"name": "level", "type": "table", "table_name": "levels", "auto_increment": "0"},
|
|
{"name": "mesh", "type": "3", "auto_increment": "0"},
|
|
{"name": "label_counter", "type": "1", "auto_increment": "0"},
|
|
{"name": "counter", "type": "1", "auto_increment": "0"},
|
|
]
|
|
|
|
var settings: SettingsData
|
|
var levels: Array[LevelEntry] = []
|
|
var scenes: Array[SceneEntry] = []
|
|
var _path: String
|
|
|
|
func _init(path: String) -> void:
|
|
_path = path
|
|
var f := FileAccess.open(path, FileAccess.READ)
|
|
if f == null:
|
|
push_error("[Database] Cannot open " + path)
|
|
return
|
|
var doc = JSON.parse_string(f.get_as_text())
|
|
f.close()
|
|
if not (doc is Dictionary):
|
|
push_error("[Database] Invalid JSON in " + path)
|
|
return
|
|
for table in doc.get("tables", []):
|
|
match table.get("table_name", ""):
|
|
"settings": settings = _load_settings(table.get("data", []))
|
|
"levels": levels = _load_levels(table.get("data", []))
|
|
"scenes": scenes = _load_scenes(table.get("data", []))
|
|
|
|
func _load_settings(data: Array) -> SettingsData:
|
|
var s := SettingsData.new()
|
|
if data.size() >= 6:
|
|
s.langue = int(data[0])
|
|
s.gyroscope = bool(int(data[1]))
|
|
s.ambient_sound = bool(int(data[2]))
|
|
s.resolution = str(data[3])
|
|
s.fullscreen = bool(int(data[4]))
|
|
s.version = str(data[5])
|
|
return s
|
|
|
|
func _load_levels(data: Array) -> Array[LevelEntry]:
|
|
var result: Array[LevelEntry] = []
|
|
const W := 2
|
|
@warning_ignore("integer_division")
|
|
for i in range(data.size() / W):
|
|
var l := LevelEntry.new()
|
|
l.index = i
|
|
l.name = str(data[i * W + 0])
|
|
l.thumb = str(data[i * W + 1])
|
|
result.append(l)
|
|
return result
|
|
|
|
func _load_scenes(data: Array) -> Array[SceneEntry]:
|
|
var result: Array[SceneEntry] = []
|
|
const W := 7
|
|
@warning_ignore("integer_division")
|
|
for i in range(data.size() / W):
|
|
var s := SceneEntry.new()
|
|
s.lock = bool(int(data[i * W + 0]))
|
|
s.label = str(data[i * W + 1])
|
|
s.key = str(data[i * W + 2])
|
|
s.level = int(data[i * W + 3])
|
|
s.mesh = str(data[i * W + 4])
|
|
s.label_counter = str(data[i * W + 5])
|
|
s.counter = int(data[i * W + 6])
|
|
result.append(s)
|
|
return result
|
|
|
|
func scenes_for_level(level_idx: int) -> Array[SceneEntry]:
|
|
var result: Array[SceneEntry] = []
|
|
for s in scenes:
|
|
if s.level == level_idx:
|
|
result.append(s)
|
|
return result
|
|
|
|
func level_by_index(idx: int) -> LevelEntry:
|
|
for l in levels:
|
|
if l.index == idx:
|
|
return l
|
|
return null
|
|
|
|
func save() -> void:
|
|
var doc := {
|
|
"GDDB_ver": "2.0",
|
|
"db_name": "ahog",
|
|
"tables": [
|
|
{"table_name": "settings", "props": _SETTINGS_PROPS, "data": _dump_settings()},
|
|
{"table_name": "levels", "props": _LEVELS_PROPS, "data": _dump_levels()},
|
|
{"table_name": "scenes", "props": _SCENES_PROPS, "data": _dump_scenes()},
|
|
],
|
|
}
|
|
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 _dump_settings() -> Array:
|
|
return [
|
|
str(settings.langue),
|
|
str(int(settings.gyroscope)),
|
|
str(int(settings.ambient_sound)),
|
|
settings.resolution,
|
|
str(int(settings.fullscreen)),
|
|
settings.version,
|
|
]
|
|
|
|
func _dump_levels() -> Array:
|
|
var out: Array = []
|
|
for l in levels:
|
|
out.append_array([l.name, l.thumb])
|
|
return out
|
|
|
|
func _dump_scenes() -> Array:
|
|
var out: Array = []
|
|
for s in scenes:
|
|
out.append_array([
|
|
str(int(s.lock)),
|
|
s.label,
|
|
s.key,
|
|
str(s.level),
|
|
s.mesh,
|
|
s.label_counter,
|
|
str(s.counter),
|
|
])
|
|
return out
|
|
|
|
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()
|