Skip to content

Commit

Permalink
Ensure entity instances have unique ids, closes #213
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbrain committed Nov 30, 2024
1 parent 1370f63 commit 4bd9f6e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 14 deletions.
4 changes: 2 additions & 2 deletions addons/pandora/api.gd
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,12 @@ func deserialize(data: Dictionary) -> PandoraEntity:
if not _loaded:
push_warning("Pandora - cannot deserialize: data not initialized yet.")
return null
if not data.has("_instanced_from_id"):
if not data.has("_instance_id"):
push_error(
"Unable to deserialize data! Not an instance! Call PandoraEntity.instantiate() to create instances."
)
return
var entity = Pandora.get_entity(data["_instanced_from_id"])
var entity = Pandora.get_entity(data["_id"])
if not entity:
return
var instance = ScriptUtil.create_entity_from_script(entity.get_script_path(), "", "", "", "")
Expand Down
25 changes: 17 additions & 8 deletions addons/pandora/model/entity.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
class_name PandoraEntity extends Resource

const ScriptUtil = preload("res://addons/pandora/util/script_util.gd")
const NanoIdGenerator = preload("res://addons/pandora/util/nanoid_generator.gd")
const CATEGORY_ICON_PATH = "res://addons/pandora/icons/Folder.svg"
const ENTITY_ICON_PATH = "res://addons/pandora/icons/Object.svg"

# we require nano ids for instances as they are non-incremental
# and instances are persisted outside of Pandora.
static var _INSTANCE_ID_GENERATOR = NanoIdGenerator.new()

signal name_changed(new_name: String)
signal order_changed(new_index: int)
signal icon_changed(new_icon_path: String)
Expand All @@ -24,7 +29,7 @@ var _icon_path: String
var _category_id: String:
get():
if is_instance():
var original = Pandora.get_entity(_instanced_from_id)
var original = Pandora.get_entity(_id)
if original:
return original._category_id
else:
Expand All @@ -48,7 +53,7 @@ var _ids_generation_class = ""

# String -> PandoraPropertyInstance
var _instance_properties: Dictionary = {}
var _instanced_from_id: String
var _instance_id: String


## Wrapper around PandoraProperty that is used to manage overrides.
Expand Down Expand Up @@ -187,12 +192,12 @@ func instantiate() -> PandoraEntity:
if entity != null:
# ensure to store the id on instances too, so scene saving does not break.
entity._id = get_entity_id()
entity._instanced_from_id = get_entity_id()
entity._instance_id = _INSTANCE_ID_GENERATOR.generate()
return entity


func is_instance() -> bool:
return _instanced_from_id != ""
return _instance_id != ""


func get_entity_id() -> String:
Expand Down Expand Up @@ -634,15 +639,19 @@ func is_category(category_id: String) -> bool:
category = Pandora.get_category(parent_id)
parent_id = category._category_id
return false


func get_entity_instance_id() -> String:
return self._instance_id


## Initializes this entity with the given data dictionary.
## Dictionary needs to confirm the structure of this entity.
func load_data(data: Dictionary) -> void:
if data.has("_id"):
_id = data["_id"]
if data.has("_instanced_from_id"):
_instanced_from_id = data["_instanced_from_id"]
if data.has("_instance_id"):
_instance_id = data["_instance_id"]
_instance_properties = _load_instance_properties(data["_instance_properties"])
else:
_name = data["_name"]
Expand Down Expand Up @@ -673,7 +682,7 @@ func save_data() -> Dictionary:
dict["_id"] = _id

if is_instance():
dict["_instanced_from_id"] = _instanced_from_id
dict["_instance_id"] = _instance_id
dict["_instance_properties"] = _save_instance_properties()
else:
dict["_name"] = _name
Expand Down Expand Up @@ -780,7 +789,7 @@ func _initialize_if_not_loaded() -> void:
func _get_instanced_from_entity() -> PandoraEntity:
if not is_instance():
return self
return Pandora.get_entity(self._instanced_from_id)
return Pandora.get_entity(self._id)


func _get_instanced_from_category() -> PandoraCategory:
Expand Down
19 changes: 15 additions & 4 deletions pandora/categories.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@
class_name PandoraCategories


const ROOT = "ZgT7rvfoPX"
const ITEMS = "1"
const RARITY = "16"
const QUESTS = "27"
const DIALOGUES = "28"
const SPELLS = "29"
const MOCK__REQUIRED_FOR_TESTING__ = "54"
const NPCS = "2"


class RootCategories:
const ITEMS = "wUsxss_qiZ"
const NPCS = "uhJOk6M0gs"
class ItemsArmoryCategories:
const SHIELDS = "8"


class ItemsCategories:
const ARMORY = "3"
const TOOLS = "4"
const ORES = "13"


17 changes: 17 additions & 0 deletions test/model/entity_test.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ func test_instantiate_entity() -> void:
var instance = entity.instantiate()
assert_that(instance.get_entity_id()).is_equal("123")
assert_bool(instance.is_instance()).is_true()
assert_that(instance.get_entity_instance_id()).is_not_equal("123")


func test_instantiate_entity_unique_instance_ids() -> void:
var entity = PandoraEntity.new()
entity.init_entity("123", "Test Entity", "res://hello.jpg", "123")
var instance_1 = entity.instantiate()
var instance_2 = entity.instantiate()
assert_that(instance_1.get_entity_instance_id()).is_not_equal(instance_2.get_entity_instance_id())


func test_duplicate_entity() -> void:
Expand All @@ -29,6 +38,14 @@ func test_duplicate_entity() -> void:
var instance = entity.duplicate_instance()
assert_that(instance.get_entity_id()).is_equal("123")
assert_bool(instance.is_instance()).is_true()


func test_duplicate_entity_unique_instance_ids() -> void:
var entity = PandoraEntity.new()
entity.init_entity("123", "Test Entity", "res://hello.jpg", "123")
var instance_1 = entity.duplicate_instance()
var instance_2 = entity.duplicate_instance()
assert_that(instance_1.get_entity_instance_id()).is_not_equal(instance_2.get_entity_instance_id())


func test_entity_set_get_vector2_property() -> void:
Expand Down

0 comments on commit 4bd9f6e

Please sign in to comment.