converting datapacks json format to use godot resources instead
This commit is contained in:
parent
410c532475
commit
2da3b9c6fa
113
sessionzero-client/scripts/helpers/datapack_creator.gd
Normal file
113
sessionzero-client/scripts/helpers/datapack_creator.gd
Normal file
@ -0,0 +1,113 @@
|
||||
# datapack_creator.gd
|
||||
class_name DatapackCreator
|
||||
extends RefCounted
|
||||
|
||||
# --- UPDATED CONSTANTS ---
|
||||
const BASE_DATAPACKS_PATH = "user://datapacks/"
|
||||
const CONTENT_SUBDIR = "objects"
|
||||
const METADATA_FILENAME = "config.szpack" # Renamed from METADATA_FILENAME
|
||||
const DATAPACK_RESOURCE_FILENAME = "datapack.tres" # Renamed from DATAPACK_RESOURCE_FILENAME
|
||||
const ASSETS_SUBDIR = "assets" # Renamed from MEDIA_SUBDIR
|
||||
|
||||
# --- INTERNAL STATE ---
|
||||
var _saved_resources: Dictionary = {}
|
||||
var _pack_base_path: String = ""
|
||||
|
||||
|
||||
# --- PUBLIC METHOD ---
|
||||
|
||||
## Saves a DatapackModel and all its content resources to the file system.
|
||||
## 'pack_name' is used to create the final folder structure: user://datapacks/[pack_name]/
|
||||
func save_datapack(datapack: DatapackModel, pack_name: String) -> bool:
|
||||
var full_pack_name = pack_name.validate_node_name()
|
||||
if full_pack_name.is_empty():
|
||||
push_error("DatapackCreator: Invalid pack_name provided.")
|
||||
return false
|
||||
|
||||
_pack_base_path = BASE_DATAPACKS_PATH + full_pack_name + "/"
|
||||
|
||||
var content_path = _pack_base_path + CONTENT_SUBDIR
|
||||
var assets_path = _pack_base_path + ASSETS_SUBDIR
|
||||
|
||||
var success_dirs = true
|
||||
success_dirs &= _make_dir_recursive_safe(_pack_base_path)
|
||||
success_dirs &= _make_dir_recursive_safe(content_path)
|
||||
success_dirs &= _make_dir_recursive_safe(assets_path)
|
||||
|
||||
if not success_dirs:
|
||||
push_error("DatapackCreator: Failed to create necessary directories.")
|
||||
return false
|
||||
|
||||
_saved_resources.clear()
|
||||
|
||||
if not _save_content_objects(datapack.content_objects, content_path + "/"):
|
||||
return false
|
||||
|
||||
var main_resource_path = _pack_base_path + DATAPACK_RESOURCE_FILENAME
|
||||
if not _save_single_resource(datapack, main_resource_path):
|
||||
return false
|
||||
|
||||
if not _write_metadata_file(datapack, _pack_base_path + METADATA_FILENAME):
|
||||
return false
|
||||
|
||||
print("Datapack saved successfully to: %s" % _pack_base_path)
|
||||
return true
|
||||
|
||||
|
||||
# --- PRIVATE HELPER METHODS ---
|
||||
|
||||
func _make_dir_recursive_safe(path: String) -> bool:
|
||||
var error = DirAccess.make_dir_recursive_absolute(path)
|
||||
if error != OK and error != ERR_ALREADY_EXISTS:
|
||||
push_error("DirAccess: Failed to create directory: %s (Error: %s)" % [path, error])
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func _save_content_objects(objects: Array, save_path: String) -> bool:
|
||||
var success = true
|
||||
for obj in objects:
|
||||
if not obj is SzObject:
|
||||
push_error("DatapackCreator: Content array contains non-SzObject: %s" % obj)
|
||||
success = false
|
||||
continue
|
||||
|
||||
# Filename format: [class_name]_[id].tres
|
||||
var filename = "%s_%s.tres" % [obj.get_class().to_lower(), obj.id.to_lower()]
|
||||
var full_path = save_path + filename
|
||||
|
||||
if not _save_single_resource(obj, full_path):
|
||||
success = false
|
||||
|
||||
return success
|
||||
|
||||
|
||||
func _save_single_resource(resource: Resource, path: String) -> bool:
|
||||
if _saved_resources.has(resource):
|
||||
return true
|
||||
|
||||
var error = ResourceSaver.save(resource, path, ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_CHANGE_PATH)
|
||||
|
||||
if error != OK:
|
||||
push_error("DatapackCreator: Failed to save resource at path '%s'. Error: %s" % [path, error])
|
||||
return false
|
||||
|
||||
_saved_resources[resource] = path
|
||||
return true
|
||||
|
||||
|
||||
func _write_metadata_file(datapack: DatapackModel, path: String) -> bool:
|
||||
var config = ConfigFile.new()
|
||||
var section = "Datapack"
|
||||
|
||||
config.set_value(section, "guid", datapack.guid.to_string())
|
||||
config.set_value(section, "name", datapack.name)
|
||||
config.set_value(section, "version", datapack.version)
|
||||
config.set_value(section, "entry_point", DATAPACK_RESOURCE_FILENAME)
|
||||
|
||||
var error = config.save(path)
|
||||
if error != OK:
|
||||
push_error("DatapackCreator: Failed to save metadata file at path '%s'. Error: %s" % [path, error])
|
||||
return false
|
||||
|
||||
return true
|
||||
@ -0,0 +1 @@
|
||||
uid://cu8n3sgejs6it
|
||||
55
sessionzero-client/scripts/helpers/datapack_loader.gd
Normal file
55
sessionzero-client/scripts/helpers/datapack_loader.gd
Normal file
@ -0,0 +1,55 @@
|
||||
# datapack_loader.gd
|
||||
class_name DatapackLoader
|
||||
extends RefCounted
|
||||
|
||||
const BASE_DATAPACKS_PATH = "user://datapacks/"
|
||||
const METADATA_FILENAME = "config.szpack"
|
||||
const DATAPACK_RESOURCE_FILENAME = "datapack.tres"
|
||||
|
||||
## Loads a DatapackModel resource and all its referenced content from the user://datapacks/ folder.
|
||||
## Returns the loaded DatapackModel object or null on failure.
|
||||
func load_datapack(pack_name: String) -> DatapackModel:
|
||||
var full_pack_name = pack_name.validate_node_name()
|
||||
if full_pack_name.is_empty():
|
||||
push_error("DatapackLoader: Invalid pack_name provided.")
|
||||
return null
|
||||
|
||||
var pack_dir = BASE_DATAPACKS_PATH + full_pack_name + "/"
|
||||
var metadata_path = pack_dir + METADATA_FILENAME
|
||||
|
||||
var config = ConfigFile.new()
|
||||
var error = config.load(metadata_path)
|
||||
|
||||
if error != OK:
|
||||
push_error("DatapackLoader: Could not load external manifest at: %s (Error: %s)" % [metadata_path, error])
|
||||
return null
|
||||
|
||||
var entry_point = config.get_value("Datapack", "entry_point", DATAPACK_RESOURCE_FILENAME)
|
||||
|
||||
var resource_path = pack_dir + entry_point
|
||||
|
||||
if not ResourceLoader.exists(resource_path):
|
||||
push_error("DatapackLoader: Main Resource file not found at path: %s" % resource_path)
|
||||
return null
|
||||
|
||||
var datapack: DatapackModel = ResourceLoader.load(resource_path)
|
||||
|
||||
if not datapack:
|
||||
push_error("DatapackLoader: Failed to load resource object from path: %s" % resource_path)
|
||||
return null
|
||||
|
||||
datapack._build_content_map()
|
||||
|
||||
print("Successfully loaded Datapack: %s (GUID: %s)" % [datapack.name, datapack.guid.to_string()])
|
||||
return datapack
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Example Usage:
|
||||
# var loader = DatapackLoader.new()
|
||||
# var core_pack = loader.load_datapack("core_rules")
|
||||
#
|
||||
# if core_pack:
|
||||
#\t var item = core_pack.get_object_by_id("sword-long")
|
||||
#\t if item:
|
||||
#\t\t print("Found item: " + item.name)
|
||||
# ----------------------------------------------------------------------
|
||||
@ -0,0 +1 @@
|
||||
uid://bwuvsyn1y3dge
|
||||
@ -1,19 +1,22 @@
|
||||
# datetime.gd
|
||||
class_name DateTime
|
||||
extends RefCounted
|
||||
extends Resource
|
||||
|
||||
@export var _unix_time: float = 0.0
|
||||
|
||||
var _unix_time: float = 0.0
|
||||
|
||||
static func now() -> DateTime:
|
||||
var dt = DateTime.new()
|
||||
dt._unix_time = Time.get_unix_time_from_system()
|
||||
return dt
|
||||
|
||||
|
||||
static func from_unix(unix_seconds: float) -> DateTime:
|
||||
var dt = DateTime.new()
|
||||
dt._unix_time = unix_seconds
|
||||
return dt
|
||||
|
||||
|
||||
static func from_string(input: String) -> DateTime:
|
||||
var s := input.strip_edges()
|
||||
if s.ends_with("Z"):
|
||||
@ -26,9 +29,11 @@ static func from_string(input: String) -> DateTime:
|
||||
dt._unix_time = unix
|
||||
return dt
|
||||
|
||||
|
||||
func to_unix() -> float:
|
||||
return _unix_time
|
||||
|
||||
|
||||
func _to_string() -> String:
|
||||
var dict := Time.get_datetime_dict_from_unix_time(_unix_time)
|
||||
return "%04d-%02d-%02dT%02d:%02d:%02dZ" % [
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
extends RefCounted
|
||||
class_name Guid
|
||||
extends Resource
|
||||
|
||||
@export var bytes: PackedByteArray
|
||||
|
||||
var bytes: PackedByteArray
|
||||
|
||||
static func new_guid() -> Guid:
|
||||
var guid = Guid.new()
|
||||
@ -11,6 +12,7 @@ static func new_guid() -> Guid:
|
||||
guid.bytes[8] = (guid.bytes[8] & 0x3F) | 0x80
|
||||
return guid
|
||||
|
||||
|
||||
static func from_string(input: String) -> Guid:
|
||||
var clean = input.replace("-", "")
|
||||
if clean.length() != 32:
|
||||
@ -22,6 +24,7 @@ static func from_string(input: String) -> Guid:
|
||||
guid.bytes.append(clean.substr(i, 2).hex_to_int())
|
||||
return guid
|
||||
|
||||
|
||||
func _to_string() -> String:
|
||||
var hex = ""
|
||||
for b in bytes:
|
||||
@ -34,10 +37,11 @@ func _to_string() -> String:
|
||||
hex.substr(20,12)
|
||||
)
|
||||
|
||||
|
||||
func to_base64() -> String:
|
||||
return Marshalls.raw_to_base64(bytes)
|
||||
|
||||
# --- internal ---
|
||||
|
||||
static func _generate_random_bytes(length: int) -> PackedByteArray:
|
||||
var arr = PackedByteArray()
|
||||
for i in range(length):
|
||||
|
||||
6
sessionzero-client/scripts/models/datapack_dependency.gd
Normal file
6
sessionzero-client/scripts/models/datapack_dependency.gd
Normal file
@ -0,0 +1,6 @@
|
||||
class_name DatapackDependency
|
||||
extends Resource
|
||||
|
||||
@export var id: Guid
|
||||
@export var name: String
|
||||
@export var version: String
|
||||
@ -0,0 +1 @@
|
||||
uid://1eht88nmv63j
|
||||
@ -1,63 +1,35 @@
|
||||
extends RefCounted
|
||||
class_name DatapackModel
|
||||
extends Resource
|
||||
|
||||
var guid: Guid
|
||||
var name: String
|
||||
var version: String
|
||||
var author: String
|
||||
var license: String
|
||||
var description: String
|
||||
var icon: String
|
||||
var created_at: DateTime
|
||||
var session_zero_version: String
|
||||
var dependencies: Array[DatapackDependency]
|
||||
@export var guid: Guid
|
||||
@export var name: String
|
||||
@export var version: String
|
||||
@export var author: String
|
||||
@export var license: String
|
||||
@export var description: String
|
||||
@export var icon: String
|
||||
@export var created_at: DateTime
|
||||
@export var session_zero_version: String
|
||||
@export var dependencies: Array[DatapackDependency] = []
|
||||
@export var sz_objects: Array[SzObject] = []
|
||||
|
||||
var content_map: Dictionary = {}
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
guid = Guid.new_guid()
|
||||
created_at = DateTime.now()
|
||||
if guid == null:
|
||||
guid = Guid.new_guid()
|
||||
if created_at == null:
|
||||
created_at = DateTime.now()
|
||||
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
var deps_arr: Array = []
|
||||
for d in dependencies:
|
||||
deps_arr.append(d.to_dict())
|
||||
return {
|
||||
"guid": guid.to_string(),
|
||||
"name": name,
|
||||
"version": version,
|
||||
"author": author,
|
||||
"license": license,
|
||||
"description": description,
|
||||
"icon": icon,
|
||||
"created_at": created_at.to_string(),
|
||||
"session_zero_version": session_zero_version,
|
||||
"dependencies": deps_arr
|
||||
}
|
||||
func _build_content_map():
|
||||
content_map.clear()
|
||||
for obj in sz_objects:
|
||||
content_map[obj.id] = obj
|
||||
|
||||
|
||||
# TODO: Implement this
|
||||
static func from_dict(dict: Dictionary) -> DatapackModel:
|
||||
var dp: DatapackModel = DatapackModel.new()
|
||||
dp.name = dict.get("name", "")
|
||||
dp.version = dict.get("version", "")
|
||||
dp.author = dict.get("author", "")
|
||||
dp.license = dict.get("license", "")
|
||||
dp.description = dict.get("description", "")
|
||||
dp.icon = dict.get("icon", "")
|
||||
dp.session_zero_version = dict.get("session_zero_version", "")
|
||||
|
||||
if dict.has("guid"):
|
||||
dp.guid = Guid.from_string(dict["guid"])
|
||||
else:
|
||||
return null
|
||||
|
||||
dp.dependencies.clear()
|
||||
if dict.has("dependencies"):
|
||||
var deps_arr: Array = dict["dependencies"]
|
||||
|
||||
for d_dict in deps_arr:
|
||||
var dependency: DatapackDependency = DatapackDependency.from_dict(d_dict)
|
||||
dp.dependencies.append(dependency)
|
||||
|
||||
return dp
|
||||
func get_object_by_id(obj_id: String) -> SzObject:
|
||||
if content_map.is_empty() and !sz_objects.is_empty():
|
||||
_build_content_map()
|
||||
return content_map.get(obj_id)
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
class_name DatapackDependency
|
||||
extends RefCounted
|
||||
|
||||
var id: Guid
|
||||
var name: String
|
||||
var version: String
|
||||
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
return {
|
||||
"id": id.to_string(),
|
||||
"name": name,
|
||||
"version": version
|
||||
}
|
||||
|
||||
|
||||
static func from_dict(dict: Dictionary) -> DatapackDependency:
|
||||
var dd := DatapackDependency.new()
|
||||
|
||||
dd.id = dict.get("id", "")
|
||||
dd.name = dict.get("name", "")
|
||||
dd.version = dict.get("version", "")
|
||||
|
||||
return dd
|
||||
@ -1 +0,0 @@
|
||||
uid://hrv66ufdp4no
|
||||
@ -1,21 +1,5 @@
|
||||
class_name DatasetModel
|
||||
extends SzObject
|
||||
|
||||
var dataset_type: String
|
||||
var entries: Dictionary[String, DatasetEntry]
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
var dict := super.to_dict()
|
||||
dict["dataset_type"] = dataset_type
|
||||
|
||||
var entries_dict := {}
|
||||
if entries:
|
||||
for key in entries.keys():
|
||||
var de := entries[key]
|
||||
if de != null:
|
||||
entries_dict[key] = de.to_dict()
|
||||
else:
|
||||
entries_dict[key] = null
|
||||
dict["entries"] = entries_dict
|
||||
|
||||
return dict
|
||||
@export var dataset_type: String
|
||||
@export var entries: Dictionary[String, DatasetEntry] = {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
class_name DataFieldValue
|
||||
extends RefCounted
|
||||
extends Resource
|
||||
|
||||
enum DataFieldType {
|
||||
TEXT,
|
||||
@ -10,8 +10,8 @@ enum DataFieldType {
|
||||
LIST
|
||||
}
|
||||
|
||||
var field_type: DataFieldType
|
||||
var value: Variant
|
||||
@export var field_type: DataFieldType
|
||||
@export var value: Variant
|
||||
|
||||
static func _type_to_string(t: DataFieldType) -> String:
|
||||
match t:
|
||||
|
||||
@ -1,32 +1,9 @@
|
||||
class_name DatasetEntry
|
||||
extends RefCounted
|
||||
extends Resource
|
||||
|
||||
var id: String
|
||||
var name: String
|
||||
var description: String
|
||||
var icon: String
|
||||
var top_level_fields: Dictionary[String, DataFieldValue]
|
||||
var groups: Array[DatasetGroup]
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
var groups_array: Array = []
|
||||
for g in groups:
|
||||
groups_array.append(g.to_json())
|
||||
|
||||
var top_level_fields_dict: Dictionary = {}
|
||||
if top_level_fields:
|
||||
for key in top_level_fields.keys():
|
||||
var dfv: DataFieldValue = top_level_fields[key]
|
||||
if dfv != null:
|
||||
top_level_fields_dict[key] = dfv.to_dict()
|
||||
else:
|
||||
top_level_fields_dict[key] = null
|
||||
|
||||
return {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"icon": icon,
|
||||
"top_level_fields": top_level_fields_dict,
|
||||
"groups": groups_array
|
||||
}
|
||||
@export var id: String
|
||||
@export var name: String
|
||||
@export var description: String
|
||||
@export var icon: String
|
||||
@export var top_level_fields: Dictionary[String, DataFieldValue]
|
||||
@export var groups: Array[DatasetGroup]
|
||||
|
||||
@ -1,23 +1,6 @@
|
||||
class_name DatasetGroup
|
||||
extends RefCounted
|
||||
extends Resource
|
||||
|
||||
var id: String
|
||||
var name: String
|
||||
var fields: Dictionary[String, DataFieldValue]
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
var fields_dict: Dictionary = {}
|
||||
if fields:
|
||||
for key in fields.keys():
|
||||
var dfv: DataFieldValue = fields[key]
|
||||
if dfv != null:
|
||||
fields_dict[key] = dfv.to_dict()
|
||||
else:
|
||||
fields_dict[key] = null
|
||||
|
||||
return {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"fields": fields_dict
|
||||
}
|
||||
@export var id: String
|
||||
@export var name: String
|
||||
@export var fields: Dictionary[String, DataFieldValue]
|
||||
|
||||
@ -1,20 +1,10 @@
|
||||
class_name SzObject
|
||||
extends RefCounted
|
||||
extends Resource
|
||||
|
||||
var id: String
|
||||
var name: String
|
||||
var sz_type: String
|
||||
var description: String
|
||||
var icon: String
|
||||
var version: String
|
||||
var schema_version: String
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
return {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"icon": icon,
|
||||
"version": version,
|
||||
"schema_version": schema_version
|
||||
}
|
||||
@export var id: String
|
||||
@export var name: String
|
||||
@export var sz_type: String
|
||||
@export var description: String
|
||||
@export var icon: String
|
||||
@export var version: String
|
||||
@export var schema_version: String
|
||||
|
||||
Loading…
Reference in New Issue
Block a user