feat: expand progression and multiplayer systems
Add named save slots, progression import/export, and a unified play flow. Add live friend requests, presence, invitations, and relationship controls without durable discovery-server social storage. Advance the network protocol with isolated channels, movement reconciliation, late-join recovery, fishing replication, and animation synchronization. Preserve per-species catch totals, refine generated-world startup and water recovery, and complete the related input and interface improvements.
This commit is contained in:
parent
1db1a5b754
commit
3b84bfe3a0
97 changed files with 7869 additions and 982 deletions
|
|
@ -82,27 +82,64 @@ func _run() -> void:
|
|||
assert(not FileAccess.file_exists(legacy_path))
|
||||
_assert_opaque(save_path)
|
||||
|
||||
save_manager.set_autosave_enabled(false)
|
||||
var save_slots := main.get("_save_slots") as PlayerSaveSlotCatalog
|
||||
assert(save_slots != null)
|
||||
assert(save_slots.configure(data_root, save_manager))
|
||||
var adopted_slots: Array[Dictionary] = save_slots.list_slots()
|
||||
assert(adopted_slots.size() == 1)
|
||||
var adopted_slot_id: String = str(adopted_slots.front().get("slot_id", ""))
|
||||
assert(bool(adopted_slots.front().get("legacy", false)))
|
||||
assert(bool(adopted_slots.front().get("has_save", false)))
|
||||
|
||||
var duplicated: Dictionary = save_slots.duplicate_slot(
|
||||
adopted_slot_id,
|
||||
"another island",
|
||||
WorldLayout.GENERATED,
|
||||
97531,
|
||||
)
|
||||
assert(bool(duplicated.get("ok", false)))
|
||||
var duplicated_slot_id: String = str(duplicated.get("slot_id", ""))
|
||||
var duplicate_summary: Dictionary = save_slots.get_slot(duplicated_slot_id)
|
||||
assert(int(duplicate_summary.get("wallet_balance", -1)) == 4321)
|
||||
assert(int(duplicate_summary.get("world_seed", -1)) == 97531)
|
||||
assert(save_slots.activate_slot(duplicated_slot_id))
|
||||
assert(save_manager.load_player_data())
|
||||
assert(player.wallet.get_balance() == 4321)
|
||||
assert(save_manager.get_world_seed() == 97531)
|
||||
assert(save_slots.rename_slot(duplicated_slot_id, "renamed island"))
|
||||
|
||||
var slot_archive: String = data_root.progression_backup_directory().path_join(
|
||||
"save-slot-export.nfsave"
|
||||
)
|
||||
assert(bool(save_slots.export_slot(
|
||||
duplicated_slot_id,
|
||||
slot_archive,
|
||||
).get("ok", false)))
|
||||
var imported_slot: Dictionary = save_slots.import_slot(
|
||||
slot_archive,
|
||||
"imported island",
|
||||
)
|
||||
assert(bool(imported_slot.get("ok", false)))
|
||||
var imported_slot_id: String = str(imported_slot.get("slot_id", ""))
|
||||
assert(not save_slots.get_slot(imported_slot_id).is_empty())
|
||||
assert(save_slots.delete_slot(duplicated_slot_id))
|
||||
assert(save_slots.get_slot(duplicated_slot_id).is_empty())
|
||||
assert(save_slots.list_slots().size() == 2)
|
||||
|
||||
var settings_panels: Array[Node] = main.find_children(
|
||||
"*", "SettingsPanel", true, false
|
||||
)
|
||||
assert(settings_panels.size() == 2)
|
||||
for settings_panel: SettingsPanel in settings_panels:
|
||||
var export_button := settings_panel.get_node(
|
||||
"%ExportProgression"
|
||||
) as Button
|
||||
var import_button := settings_panel.get_node(
|
||||
"%ImportProgression"
|
||||
) as Button
|
||||
assert(export_button != null and import_button != null)
|
||||
assert(not export_button.disabled and not import_button.disabled)
|
||||
assert(
|
||||
export_button.get_node(export_button.focus_neighbor_right)
|
||||
== import_button
|
||||
)
|
||||
assert(
|
||||
import_button.get_node(import_button.focus_neighbor_left)
|
||||
== export_button
|
||||
)
|
||||
assert(settings_panel.get_node_or_null("%ExportProgression") == null)
|
||||
assert(settings_panel.get_node_or_null("%ImportProgression") == null)
|
||||
var save_slots_page := main.find_child(
|
||||
"SaveSlotsPage", true, false
|
||||
) as SaveSlotsPage
|
||||
assert(save_slots_page != null)
|
||||
assert(save_slots_page.get_node("%ExportSlotButton") is Button)
|
||||
assert(save_slots_page.get_node("%ImportSlotButton") is Button)
|
||||
|
||||
var migrated_root: String = data_root.root_path.get_base_dir().path_join(
|
||||
"progression-migrated-data"
|
||||
|
|
@ -118,6 +155,18 @@ func _run() -> void:
|
|||
assert(bool(
|
||||
ProgressionSaveCodec.read_local_save(migrated_save).get("ok", false)
|
||||
))
|
||||
assert(FileAccess.file_exists(migrated_root.path_join(
|
||||
"player/save_slots.json"
|
||||
)))
|
||||
var migrated_imported_slot: String = migrated_root.path_join(
|
||||
"player/saves/%s.nfsave" % imported_slot_id
|
||||
)
|
||||
assert(FileAccess.file_exists(migrated_imported_slot))
|
||||
assert(bool(
|
||||
ProgressionSaveCodec.read_local_save(migrated_imported_slot).get(
|
||||
"ok", false
|
||||
)
|
||||
))
|
||||
|
||||
main.queue_free()
|
||||
for _frame: int in 4:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue