146 lines
3.7 KiB
GDScript
146 lines
3.7 KiB
GDScript
class_name WorldObject
|
|
extends RefCounted
|
|
## A world object (static or dynamic) within a chunk.
|
|
##
|
|
## This is the runtime representation of a WorldObject from the chunk data
|
|
## format (see docs/architecture/world.md §3.3). It holds the object's
|
|
## identity, transform, properties, and moderation flags.
|
|
|
|
## Stable object ID, unique within the chunk.
|
|
var id: String = ""
|
|
|
|
## Object type (e.g. "prop", "interactable", "spawn_point", "door").
|
|
var type: String = ""
|
|
|
|
## Reference to the object's mesh/glTF asset.
|
|
var asset_id: String = ""
|
|
|
|
## World-space position.
|
|
var position: Vector3 = Vector3.ZERO
|
|
|
|
## World-space rotation as a quaternion (x, y, z, w).
|
|
var rotation: Vector4 = Vector4(0, 0, 0, 1)
|
|
|
|
## World-space scale.
|
|
var scale: Vector3 = Vector3.ONE
|
|
|
|
## Type-specific key/value properties.
|
|
var properties: Dictionary = {}
|
|
|
|
## Parent object ID when stacked on top of or attached to another object.
|
|
var parent_id: String = ""
|
|
|
|
## Whether this is a spawnable dynamic entity (true) or static (false).
|
|
var is_dynamic: bool = false
|
|
|
|
## Per-object content moderation flags.
|
|
var flags: ChunkDataDecoder.ContentFlags = ChunkDataDecoder.ContentFlags.new()
|
|
|
|
## Whether this object has been modified locally.
|
|
var is_dirty: bool = false
|
|
|
|
|
|
func _init(
|
|
p_id: String = "",
|
|
p_type: String = "",
|
|
p_asset_id: String = "",
|
|
p_position: Vector3 = Vector3.ZERO,
|
|
p_rotation: Vector4 = Vector4(0, 0, 0, 1),
|
|
p_scale: Vector3 = Vector3.ONE,
|
|
p_properties: Dictionary = {},
|
|
p_dynamic: bool = false,
|
|
p_flags: ChunkDataDecoder.ContentFlags = null
|
|
) -> void:
|
|
id = p_id
|
|
type = p_type
|
|
asset_id = p_asset_id
|
|
position = p_position
|
|
rotation = p_rotation
|
|
scale = p_scale
|
|
properties = p_properties
|
|
parent_id = str(properties.get("parent_id", ""))
|
|
is_dynamic = p_dynamic
|
|
if p_flags != null:
|
|
flags = p_flags
|
|
|
|
|
|
## Get a property value by key.
|
|
func get_property(key: String) -> Variant:
|
|
return properties.get(key)
|
|
|
|
|
|
## Set a property value.
|
|
func set_property(key: String, value: Variant) -> void:
|
|
properties[key] = value
|
|
is_dirty = true
|
|
|
|
|
|
## Check if this object is walkable (based on properties).
|
|
func is_walkable() -> bool:
|
|
return properties.get("walkable", true)
|
|
|
|
|
|
## Check if this object is climbable (based on properties).
|
|
func is_climbable() -> bool:
|
|
return properties.get("climbable", false)
|
|
|
|
|
|
## Check if this object is interactable.
|
|
func is_interactable() -> bool:
|
|
return type == "interactable" or properties.get("interactable", false)
|
|
|
|
|
|
## Get the object's display name.
|
|
func get_display_name() -> String:
|
|
return properties.get("display_name", id)
|
|
|
|
|
|
## Serialize this object to a dictionary (for networking).
|
|
func to_dict() -> Dictionary:
|
|
var d := {
|
|
"id": id,
|
|
"type": type,
|
|
"asset_id": asset_id,
|
|
"position": [position.x, position.y, position.z],
|
|
"rotation": [rotation.x, rotation.y, rotation.z, rotation.w],
|
|
"scale": [scale.x, scale.y, scale.z],
|
|
"properties": properties,
|
|
"dynamic": is_dynamic,
|
|
}
|
|
if parent_id != "":
|
|
d["parent_id"] = parent_id
|
|
return d
|
|
|
|
|
|
## Create a WorldObject from a dictionary (for networking).
|
|
static func from_dict(d: Dictionary) -> WorldObject:
|
|
var pos := Vector3(
|
|
d.get("position", [0, 0, 0])[0],
|
|
d.get("position", [0, 0, 0])[1],
|
|
d.get("position", [0, 0, 0])[2]
|
|
)
|
|
var rot := Vector4(
|
|
d.get("rotation", [0, 0, 0, 1])[0],
|
|
d.get("rotation", [0, 0, 0, 1])[1],
|
|
d.get("rotation", [0, 0, 0, 1])[2],
|
|
d.get("rotation", [0, 0, 0, 1])[3]
|
|
)
|
|
var scl := Vector3(
|
|
d.get("scale", [1, 1, 1])[0],
|
|
d.get("scale", [1, 1, 1])[1],
|
|
d.get("scale", [1, 1, 1])[2]
|
|
)
|
|
var props: Dictionary = d.get("properties", {}).duplicate()
|
|
if d.has("parent_id") and not props.has("parent_id"):
|
|
props["parent_id"] = d["parent_id"]
|
|
return WorldObject.new(
|
|
d.get("id", ""),
|
|
d.get("type", ""),
|
|
d.get("asset_id", ""),
|
|
pos,
|
|
rot,
|
|
scl,
|
|
props,
|
|
d.get("dynamic", false),
|
|
)
|