From 3f53502a5907ed1982d28a392c54331f0c1c2c42 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 25 Sep 2025 12:09:50 -0400 Subject: Move the client into the apworld Only works on source right now, not as an apworld. --- client/Archipelago/client.gd | 417 ------------------------------------------- 1 file changed, 417 deletions(-) delete mode 100644 client/Archipelago/client.gd (limited to 'client/Archipelago/client.gd') diff --git a/client/Archipelago/client.gd b/client/Archipelago/client.gd deleted file mode 100644 index 843647d..0000000 --- a/client/Archipelago/client.gd +++ /dev/null @@ -1,417 +0,0 @@ -extends Node - -const ap_version = {"major": 0, "minor": 6, "build": 3, "class": "Version"} - -var SCRIPT_uuid - -var _ws = WebSocketPeer.new() -var _should_process = false -var _initiated_disconnect = false -var _try_wss = false -var _has_connected = false - -var _datapackages = {} -var _pending_packages = [] -var _item_id_to_name = {} # All games -var _location_id_to_name = {} # All games -var _item_name_to_id = {} # Lingo 2 only -var _location_name_to_id = {} # Lingo 2 only - -var _remote_version = {"major": 0, "minor": 0, "build": 0} -var _gen_version = {"major": 0, "minor": 0, "build": 0} - -var ap_server = "" -var ap_user = "" -var ap_pass = "" - -var _authenticated = false -var _seed = "" -var _team = 0 -var _slot = 0 -var _players = [] -var _player_name_by_slot = {} -var _game_by_player = {} -var _checked_locations = [] -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, amount) -signal message_received(message) -signal location_scout_received(item_id, location_id, player, flags) - - -func _init(): - set_process_mode(Node.PROCESS_MODE_ALWAYS) - - _ws.inbound_buffer_size = 8388608 - - global._print("Instantiated APClient") - - # Read AP datapackages from file, if there are any - if FileAccess.file_exists("user://ap_datapackages"): - var file = FileAccess.open("user://ap_datapackages", FileAccess.READ) - var data = file.get_var(true) - file.close() - - if typeof(data) != TYPE_DICTIONARY: - global._print("AP datapackages file is corrupted") - data = {} - - _datapackages = data - - processDatapackages() - - -func _ready(): - pass - #_ws.connect("connection_closed", _closed) - #_ws.connect("connection_failed", _closed) - #_ws.connect("server_disconnected", _closed) - #_ws.connect("connection_error", _errored) - #_ws.connect("connection_established", _connected) - - -func _reset_state(): - _should_process = false - _authenticated = false - _try_wss = false - _has_connected = false - _received_items = {} - _received_indexes = [] - - -func _errored(): - if _try_wss: - global._print("Could not connect to AP with ws://, now trying wss://") - connectToServer(ap_server, ap_user, ap_pass) - else: - global._print("AP connection failed") - _reset_state() - - emit_signal( - "could_not_connect", - "Could not connect to Archipelago. Check that your server and port are correct. See the error log for more information." - ) - - -func _closed(_was_clean = true): - global._print("Connection closed") - _reset_state() - - if not _initiated_disconnect: - emit_signal("could_not_connect", "Disconnected from Archipelago") - - _initiated_disconnect = false - - -func _connected(_proto = ""): - global._print("Connected!") - _try_wss = false - - -func disconnect_from_ap(): - _initiated_disconnect = true - _ws.close() - - -func _process(_delta): - if _should_process: - _ws.poll() - - var state = _ws.get_ready_state() - if state == WebSocketPeer.STATE_OPEN: - if not _has_connected: - _has_connected = true - - _connected() - - while _ws.get_available_packet_count(): - var packet = _ws.get_packet() - global._print("Got data from server: " + packet.get_string_from_utf8()) - var json = JSON.new() - var jserror = json.parse(packet.get_string_from_utf8()) - if jserror != OK: - global._print("Error parsing packet from AP: " + jserror.error_string) - return - - for message in json.data: - var cmd = message["cmd"] - global._print("Received command: " + cmd) - - if cmd == "RoomInfo": - _seed = message["seed_name"] - _remote_version = message["version"] - _gen_version = message["generator_version"] - - var needed_games = [] - for game in message["datapackage_checksums"].keys(): - if ( - !_datapackages.has(game) - or ( - _datapackages[game]["checksum"] - != message["datapackage_checksums"][game] - ) - ): - needed_games.append(game) - - if !needed_games.is_empty(): - _pending_packages = needed_games - var cur_needed = _pending_packages.pop_front() - requestDatapackages([cur_needed]) - else: - connectToRoom() - - elif cmd == "DataPackage": - for game in message["data"]["games"].keys(): - _datapackages[game] = message["data"]["games"][game] - saveDatapackages() - - if !_pending_packages.is_empty(): - var cur_needed = _pending_packages.pop_front() - requestDatapackages([cur_needed]) - else: - processDatapackages() - connectToRoom() - - elif cmd == "Connected": - _authenticated = true - _team = message["team"] - _slot = message["slot"] - _players = message["players"] - _checked_locations = message["checked_locations"] - _slot_data = message["slot_data"] - - for player in _players: - _player_name_by_slot[player["slot"]] = player["alias"] - _game_by_player[player["slot"]] = message["slot_info"][str( - player["slot"] - )]["game"] - - emit_signal("client_connected", _slot_data) - - elif cmd == "ConnectionRefused": - var error_message = "" - for error in message["errors"]: - var submsg = "" - if error == "InvalidSlot": - submsg = "Invalid player name." - elif error == "InvalidGame": - submsg = "The specified player is not playing Lingo." - elif error == "IncompatibleVersion": - submsg = ( - "The Archipelago server is not the correct version for this client. Expected v%d.%d.%d. Found v%d.%d.%d." - % [ - ap_version["major"], - ap_version["minor"], - ap_version["build"], - _remote_version["major"], - _remote_version["minor"], - _remote_version["build"] - ] - ) - elif error == "InvalidPassword": - submsg = "Incorrect password." - elif error == "InvalidItemsHandling": - submsg = "Invalid item handling flag. This is a bug with the client." - - if submsg != "": - if error_message != "": - error_message += " " - error_message += submsg - - if error_message == "": - error_message = "Unknown error." - - _initiated_disconnect = true - _ws.close() - - emit_signal("could_not_connect", error_message) - global._print("Connection to AP refused") - global._print(message) - - elif cmd == "ReceivedItems": - var i = 0 - for item in message["items"]: - 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", - item_id, - index, - int(item["player"]), - int(item["flags"]), - _received_items[item_id] - ) - - elif cmd == "PrintJSON": - emit_signal("message_received", message) - - elif cmd == "LocationInfo": - for loc in message["locations"]: - emit_signal( - "location_scout_received", - int(loc["item"]), - int(loc["location"]), - int(loc["player"]), - int(loc["flags"]) - ) - - elif state == WebSocketPeer.STATE_CLOSED: - if _has_connected: - _closed() - else: - _errored() - - -func saveDatapackages(): - # Save the AP datapackages to disk. - var file = FileAccess.open("user://ap_datapackages", FileAccess.WRITE) - file.store_var(_datapackages, true) - file.close() - - -func connectToServer(server, un, pw): - ap_server = server - ap_user = un - ap_pass = pw - - _initiated_disconnect = false - - var url = "" - if ap_server.begins_with("ws://") or ap_server.begins_with("wss://"): - url = ap_server - _try_wss = false - elif _try_wss: - url = "wss://" + ap_server - _try_wss = false - else: - url = "ws://" + ap_server - _try_wss = true - - var err = _ws.connect_to_url(url) - if err != OK: - emit_signal( - "could_not_connect", - ( - "Could not connect to Archipelago. Check that your server and port are correct. See the error log for more information. Error code: %d." - % err - ) - ) - global._print("Could not connect to AP: %d" % err) - return - _should_process = true - - emit_signal("connect_status", "Connecting...") - - -func sendMessage(msg): - var payload = JSON.stringify(msg) - _ws.send_text(payload) - - -func requestDatapackages(games): - emit_signal("connect_status", "Downloading %s data package..." % games[0]) - - sendMessage([{"cmd": "GetDataPackage", "games": games}]) - - -func processDatapackages(): - _item_id_to_name = {} - _location_id_to_name = {} - for game in _datapackages.keys(): - var package = _datapackages[game] - - _item_id_to_name[game] = {} - for item_name in package["item_name_to_id"].keys(): - _item_id_to_name[game][int(package["item_name_to_id"][item_name])] = item_name - - _location_id_to_name[game] = {} - for location_name in package["location_name_to_id"].keys(): - _location_id_to_name[game][int(package["location_name_to_id"][location_name])] = location_name - - if _datapackages.has("Lingo 2"): - _item_name_to_id = _datapackages["Lingo 2"]["item_name_to_id"] - _location_name_to_id = _datapackages["Lingo 2"]["location_name_to_id"] - - -func connectToRoom(): - emit_signal("connect_status", "Authenticating...") - - sendMessage( - [ - { - "cmd": "Connect", - "password": ap_pass, - "game": "Lingo 2", - "name": ap_user, - "uuid": SCRIPT_uuid.v4(), - "version": ap_version, - "items_handling": 0b111, # always receive our items - "tags": [], - "slot_data": true - } - ] - ) - - -func sendConnectUpdate(tags): - sendMessage([{"cmd": "ConnectUpdate", "tags": tags}]) - - -func requestSync(): - sendMessage([{"cmd": "Sync"}]) - - -func sendLocation(loc_id): - sendMessage([{"cmd": "LocationChecks", "locations": [loc_id]}]) - - -func sendLocations(loc_ids): - sendMessage([{"cmd": "LocationChecks", "locations": loc_ids}]) - - -func setValue(key, value, operation = "replace"): - sendMessage( - [ - { - "cmd": "Set", - "key": "Lingo2_%d_%s" % [_slot, key], - "want_reply": false, - "operations": [{"operation": operation, "value": value}] - } - ] - ) - - -func say(textdata): - sendMessage([{"cmd": "Say", "text": textdata}]) - - -func completedGoal(): - sendMessage([{"cmd": "StatusUpdate", "status": 30}]) # CLIENT_GOAL - - -func scoutLocations(loc_ids): - sendMessage([{"cmd": "LocationScouts", "locations": loc_ids}]) - - -func hasItem(item_id): - return _received_items.has(item_id) - - -func getItemAmount(item_id): - return _received_items.get(item_id, 0) -- cgit 1.4.1