fix(multiplayer): replicate per-player avatar loadout and preserve original materials
checkpoint / checkpoint (push) Successful in 5m57s
checkpoint / checkpoint (push) Successful in 5m57s
This commit is contained in:
@@ -249,14 +249,42 @@ func has_loadout() -> bool:
|
||||
func ensure_catalog() -> bool:
|
||||
if is_catalog_loaded:
|
||||
return true
|
||||
return load_catalog() == OK
|
||||
var ok := load_catalog() == OK
|
||||
if ok and current_loadout == null:
|
||||
_try_load_cached_loadout()
|
||||
return ok
|
||||
|
||||
|
||||
func _try_load_cached_loadout() -> void:
|
||||
if FileAccess.file_exists("user://loadout.json"):
|
||||
var f := FileAccess.open("user://loadout.json", FileAccess.READ)
|
||||
if f != null:
|
||||
var txt := f.get_as_text()
|
||||
f.close()
|
||||
var dict: Variant = JSON.parse_string(txt)
|
||||
if dict is Dictionary:
|
||||
set_loadout_from_dict(dict as Dictionary)
|
||||
|
||||
|
||||
## Return the current loadout as a dictionary. If none is set, returns a default
|
||||
## loadout using the first available base body, or {} if catalog is empty.
|
||||
func get_current_loadout_dict() -> Dictionary:
|
||||
if current_loadout != null:
|
||||
return current_loadout.to_dict()
|
||||
ensure_catalog()
|
||||
if current_loadout != null:
|
||||
return current_loadout.to_dict()
|
||||
var bases := get_assets_for_slot("base_body")
|
||||
if not bases.is_empty():
|
||||
return {"base_body": bases[0], "slots": {}}
|
||||
return {}
|
||||
|
||||
|
||||
## Set the current player's loadout from the dict shape the backend's
|
||||
## GET /api/avatar/loadout returns (i.e. AvatarLoadout.to_json() parsed).
|
||||
## Returns true if it validated and was stored.
|
||||
func set_loadout_from_dict(loadout_dict: Dictionary) -> bool:
|
||||
var lo := AvatarLoadout.from_json(JSON.stringify(loadout_dict))
|
||||
var lo := AvatarLoadout.from_dict(loadout_dict)
|
||||
if not lo.validate():
|
||||
push_warning("AvatarSystem: rejecting invalid loadout dict: %s"
|
||||
% str(lo.validation_errors))
|
||||
@@ -287,24 +315,35 @@ func build_current_avatar() -> Node3D:
|
||||
## Assemble a standalone avatar node from [param loadout] using a throwaway
|
||||
## loader -- unlike load_avatar(), this touches no shared state, so it's safe
|
||||
## to call many times (local player + one per remote peer). Returns null only
|
||||
## if the assets are genuinely missing.
|
||||
## if the assets are genuinely missing. Accepts either AvatarLoadout or Dictionary.
|
||||
func assemble_avatar(loadout) -> Node3D:
|
||||
if loadout == null or not is_catalog_loaded:
|
||||
if loadout == null:
|
||||
return null
|
||||
var validation := catalog.validate_loadout(loadout)
|
||||
if not ensure_catalog():
|
||||
return null
|
||||
|
||||
var lo: AvatarLoadout = null
|
||||
if loadout is AvatarLoadout:
|
||||
lo = loadout
|
||||
elif loadout is Dictionary:
|
||||
lo = AvatarLoadout.from_dict(loadout as Dictionary)
|
||||
else:
|
||||
return null
|
||||
|
||||
var validation := catalog.validate_loadout(lo)
|
||||
if not validation.valid:
|
||||
push_warning("AvatarSystem: invalid loadout, skipping: %s" % str(validation.errors))
|
||||
return null
|
||||
|
||||
var l = AvatarLoader.new()
|
||||
l.init_loader(catalog)
|
||||
var base := l.load_base_body(loadout.base_body)
|
||||
var base := l.load_base_body(lo.base_body)
|
||||
if base == null:
|
||||
l.free()
|
||||
return null
|
||||
|
||||
for slot_id in AvatarSlotRegistry.SLOT_IDS:
|
||||
var v = loadout.slots.get(slot_id)
|
||||
var v = lo.slots.get(slot_id)
|
||||
if slot_id == "accessory":
|
||||
if v is Array:
|
||||
for aid in v:
|
||||
@@ -314,11 +353,11 @@ func assemble_avatar(loadout) -> Node3D:
|
||||
l.load_attachment(slot_id, v)
|
||||
|
||||
for slot_id in AvatarSlotRegistry.BODY_PART_SLOTS:
|
||||
var v = loadout.slots.get(slot_id)
|
||||
var v = lo.slots.get(slot_id)
|
||||
if v is String and not (v as String).is_empty():
|
||||
l.set_base_mesh_visible(slot_id, false)
|
||||
|
||||
l.apply_skin_tone(loadout.skin_tone)
|
||||
l.apply_skin_tone(lo.skin_tone)
|
||||
|
||||
l.free()
|
||||
return base
|
||||
|
||||
Reference in New Issue
Block a user