From 7f5f14ddb5a67e1ccfdc7aa3d68d829473d0b745 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Mon, 1 Sep 2025 14:50:47 -0400 Subject: [Client] Handle progressive doors --- client/Archipelago/animationListener.gd | 14 +++---- client/Archipelago/client.gd | 32 +++++++++++---- client/Archipelago/door.gd | 14 +++---- client/Archipelago/gamedata.gd | 4 ++ client/Archipelago/manager.gd | 70 ++++++++++++++++++++------------- client/Archipelago/painting.gd | 14 +++---- client/Archipelago/teleportListener.gd | 14 +++---- 7 files changed, 99 insertions(+), 63 deletions(-) diff --git a/client/Archipelago/animationListener.gd b/client/Archipelago/animationListener.gd index f1fb5fb..c3b26db 100644 --- a/client/Archipelago/animationListener.gd +++ b/client/Archipelago/animationListener.gd @@ -1,6 +1,7 @@ extends "res://scripts/nodes/listeners/animationListener.gd" var item_id +var item_amount func _ready(): @@ -8,17 +9,16 @@ func _ready(): get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names() ) - print("node: %s" % node_path) - var gamedata = global.get_node("Gamedata") var door_id = gamedata.get_door_for_map_node_path(global.map, node_path) if door_id != null: - print("door_id: %d" % door_id) - var ap = global.get_node("Archipelago") - item_id = ap.get_item_id_for_door(door_id) + var item_lock = ap.get_item_id_for_door(door_id) + + if item_lock != null: + item_id = item_lock[0] + item_amount = item_lock[1] - if item_id != null: self.senders = [] self.senderGroup = [] self.nested = false @@ -34,5 +34,5 @@ func _ready(): func _readier(): var ap = global.get_node("Archipelago") - if ap.has_item(item_id): + if ap.client.getItemAmount(item_id) >= item_amount: handleTriggered() diff --git a/client/Archipelago/client.gd b/client/Archipelago/client.gd index f0f36d7..52ce047 100644 --- a/client/Archipelago/client.gd +++ b/client/Archipelago/client.gd @@ -32,13 +32,14 @@ var _players = [] var _player_name_by_slot = {} var _game_by_player = {} var _checked_locations = [] -var _received_items = [] +var _received_indexes = [] +var _received_items = {} var _slot_data = {} signal could_not_connect signal connect_status signal client_connected(slot_data) -signal item_received(item_id, index, player, flags) +signal item_received(item_id, index, player, flags, amount) signal message_received(message) @@ -74,6 +75,8 @@ func _reset_state(): _authenticated = false _try_wss = false _has_connected = false + _received_items = {} + _received_indexes = [] func _errored(): @@ -228,17 +231,26 @@ func _process(_delta): elif cmd == "ReceivedItems": var i = 0 for item in message["items"]: - if not _received_items.has(int(item["item"])): - _received_items.append(int(item["item"])) + var index = int(message["index"] + i) + i += 1 + + if _received_indexes.has(index): + # Do not re-process items. + continue + + _received_indexes.append(index) + + var item_id = int(item["item"]) + _received_items[item_id] = _received_items.get(item_id, 0) + 1 emit_signal( "item_received", - int(item["item"]), - int(message["index"]) + i, + item_id, + index, int(item["player"]), - int(item["flags"]) + int(item["flags"]), + _received_items[item_id] ) - i += 1 elif cmd == "PrintJSON": emit_signal("message_received", message) @@ -380,3 +392,7 @@ func completedGoal(): func hasItem(item_id): return _received_items.has(item_id) + + +func getItemAmount(item_id): + return _received_items.get(item_id, 0) diff --git a/client/Archipelago/door.gd b/client/Archipelago/door.gd index 731eca4..fead818 100644 --- a/client/Archipelago/door.gd +++ b/client/Archipelago/door.gd @@ -1,6 +1,7 @@ extends "res://scripts/nodes/door.gd" var item_id +var item_amount func _ready(): @@ -8,17 +9,16 @@ func _ready(): get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names() ) - print("node: %s" % node_path) - var gamedata = global.get_node("Gamedata") var door_id = gamedata.get_door_for_map_node_path(global.map, node_path) if door_id != null: - print("door_id: %d" % door_id) - var ap = global.get_node("Archipelago") - item_id = ap.get_item_id_for_door(door_id) + var item_lock = ap.get_item_id_for_door(door_id) + + if item_lock != null: + item_id = item_lock[0] + item_amount = item_lock[1] - if item_id != null: self.senders = [] self.senderGroup = [] self.nested = false @@ -34,5 +34,5 @@ func _ready(): func _readier(): var ap = global.get_node("Archipelago") - if ap.has_item(item_id): + if ap.client.getItemAmount(item_id) >= item_amount: handleTriggered() diff --git a/client/Archipelago/gamedata.gd b/client/Archipelago/gamedata.gd index 16368a9..669ad3d 100644 --- a/client/Archipelago/gamedata.gd +++ b/client/Archipelago/gamedata.gd @@ -7,6 +7,7 @@ var door_id_by_map_node_path = {} var painting_id_by_map_node_path = {} var door_id_by_ap_id = {} var map_id_by_name = {} +var progressive_id_by_ap_id = {} func _init(proto_script): @@ -50,6 +51,9 @@ func load(data_bytes): var _map_data = painting_id_by_map_node_path[map.get_name()] + for progressive in objects.get_progressives(): + progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id() + func get_door_for_map_node_path(map_name, node_path): if not door_id_by_map_node_path.has(map_name): diff --git a/client/Archipelago/manager.gd b/client/Archipelago/manager.gd index 97c556a..0186a09 100644 --- a/client/Archipelago/manager.gd +++ b/client/Archipelago/manager.gd @@ -15,12 +15,13 @@ var connection_history = [] var client var _localdata_file = "" -var _received_indexes = [] var _last_new_item = -1 var _batch_locations = false var _held_locations = [] +var _item_locks = {} var victory_condition = -1 +var shuffle_doors = false signal could_not_connect signal connect_status @@ -96,7 +97,6 @@ func saveLocaldata(): func connectToServer(): - _received_indexes = [] _last_new_item = -1 client.connectToServer(ap_server, ap_user, ap_pass) @@ -111,35 +111,25 @@ func disconnect_from_ap(): func get_item_id_for_door(door_id): - var gamedata = global.get_node("Gamedata") - var door = gamedata.objects.get_doors()[door_id] - if ( - door.get_type() == gamedata.SCRIPT_proto.DoorType.EVENT - or door.get_type() == gamedata.SCRIPT_proto.DoorType.LOCATION_ONLY - or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR - ): - return null - return gamedata.get_door_ap_id(door_id) - - -func has_item(item_id): - return client.hasItem(item_id) - - -func _process_item(item, index, from, flags): - if index != null: - if _received_indexes.has(index): - # Do not re-process items. - return + return _item_locks.get(door_id, null) - _received_indexes.append(index) +func _process_item(item, index, from, flags, amount): var item_name = "Unknown" if client._item_id_to_name["Lingo 2"].has(item): item_name = client._item_id_to_name["Lingo 2"][item] var gamedata = global.get_node("Gamedata") var door_id = gamedata.door_id_by_ap_id.get(item, null) + var prog_id = null + + if door_id == null: + prog_id = gamedata.progressive_id_by_ap_id.get(item, null) + if prog_id != null: + var progressive = gamedata.objects.get_progressives()[prog_id] + if progressive.get_doors().size() >= amount: + door_id = progressive.get_doors()[amount - 1] + if door_id != null and gamedata.get_door_map_name(door_id) == global.map: var receivers = gamedata.get_door_receivers(door_id) var scene = get_tree().get_root().get_node_or_null("scene") @@ -165,11 +155,18 @@ func _process_item(item, index, from, flags): var item_color = colorForItemType(flags) + var full_item_name = item_name + if prog_id != null and door_id != null: + var door = gamedata.objects.get_doors()[door_id] + full_item_name = "%s (%s)" % [item_name, door.get_name()] + var message if from == client._slot: - message = "Found [color=%s]%s[/color]" % [item_color, item_name] + message = "Found [color=%s]%s[/color]" % [item_color, full_item_name] else: - message = "Received [color=%s]%s[/color] from %s" % [item_color, item_name, player_name] + message = ( + "Received [color=%s]%s[/color] from %s" % [item_color, full_item_name, player_name] + ) global._print(message) @@ -271,6 +268,8 @@ func _client_connect_status(message): func _client_connected(slot_data): + var gamedata = global.get_node("Gamedata") + _localdata_file = "user://archipelago_data/%s_%d" % [client._seed, client._slot] _last_new_item = -1 @@ -288,8 +287,25 @@ func _client_connected(slot_data): if localdata.size() > 0: _last_new_item = localdata[0] - if slot_data.has("victory_condition"): - victory_condition = int(slot_data["victory_condition"]) + # Read slot data. + victory_condition = int(slot_data.get("victory_condition", 0)) + shuffle_doors = bool(slot_data.get("shuffle_doors", false)) + + # Set up item locks. + _item_locks = {} + + if shuffle_doors: + for door in gamedata.objects.get_doors(): + if ( + door.get_type() == gamedata.SCRIPT_proto.DoorType.STANDARD + or door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY + ): + _item_locks[door.get_id()] = [door.get_ap_id(), 1] + + for progressive in gamedata.objects.get_progressives(): + for i in range(0, progressive.get_doors().size()): + var door = gamedata.objects.get_doors()[progressive.get_doors()[i]] + _item_locks[door.get_id()] = [progressive.get_ap_id(), i + 1] emit_signal("ap_connected") diff --git a/client/Archipelago/painting.gd b/client/Archipelago/painting.gd index 6b3de0b..276d4eb 100644 --- a/client/Archipelago/painting.gd +++ b/client/Archipelago/painting.gd @@ -1,6 +1,7 @@ extends "res://scripts/nodes/painting.gd" var item_id +var item_amount func _ready(): @@ -8,17 +9,16 @@ func _ready(): get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names() ) - print("node: %s" % node_path) - var gamedata = global.get_node("Gamedata") var door_id = gamedata.get_door_for_map_node_path(global.map, node_path) if door_id != null: - print("door_id: %d" % door_id) - var ap = global.get_node("Archipelago") - item_id = ap.get_item_id_for_door(door_id) + var item_lock = ap.get_item_id_for_door(door_id) + + if item_lock != null: + item_id = item_lock[0] + item_amount = item_lock[1] - if item_id != null: self.senders = [] self.senderGroup = [] self.nested = false @@ -34,5 +34,5 @@ func _ready(): func _readier(): var ap = global.get_node("Archipelago") - if ap.has_item(item_id): + if ap.client.getItemAmount(item_id) >= item_amount: handleTriggered() diff --git a/client/Archipelago/teleportListener.gd b/client/Archipelago/teleportListener.gd index 4bb08c9..4a7deec 100644 --- a/client/Archipelago/teleportListener.gd +++ b/client/Archipelago/teleportListener.gd @@ -1,6 +1,7 @@ extends "res://scripts/nodes/listeners/teleportListener.gd" var item_id +var item_amount func _ready(): @@ -8,17 +9,16 @@ func _ready(): get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names() ) - print("node: %s" % node_path) - var gamedata = global.get_node("Gamedata") var door_id = gamedata.get_door_for_map_node_path(global.map, node_path) if door_id != null: - print("door_id: %d" % door_id) - var ap = global.get_node("Archipelago") - item_id = ap.get_item_id_for_door(door_id) + var item_lock = ap.get_item_id_for_door(door_id) + + if item_lock != null: + item_id = item_lock[0] + item_amount = item_lock[1] - if item_id != null: self.senders = [] self.senderGroup = [] self.nested = false @@ -34,5 +34,5 @@ func _ready(): func _readier(): var ap = global.get_node("Archipelago") - if ap.has_item(item_id): + if ap.client.getItemAmount(item_id) >= item_amount: handleTriggered() -- cgit 1.4.1