diff options
Diffstat (limited to 'apworld/client/client.gd')
| -rw-r--r-- | apworld/client/client.gd | 265 |
1 files changed, 265 insertions, 0 deletions
| diff --git a/apworld/client/client.gd b/apworld/client/client.gd new file mode 100644 index 0000000..62d7fd8 --- /dev/null +++ b/apworld/client/client.gd | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | extends Node | ||
| 2 | |||
| 3 | const ap_version = {"major": 0, "minor": 6, "build": 3, "class": "Version"} | ||
| 4 | |||
| 5 | var SCRIPT_websocketserver | ||
| 6 | |||
| 7 | var _server | ||
| 8 | var _should_process = false | ||
| 9 | |||
| 10 | var _remote_version = {"major": 0, "minor": 0, "build": 0} | ||
| 11 | var _gen_version = {"major": 0, "minor": 0, "build": 0} | ||
| 12 | |||
| 13 | var ap_server = "" | ||
| 14 | var ap_user = "" | ||
| 15 | var ap_pass = "" | ||
| 16 | |||
| 17 | var _seed = "" | ||
| 18 | var _team = 0 | ||
| 19 | var _slot = 0 | ||
| 20 | var _checked_locations = [] | ||
| 21 | var _checked_worldports = [] | ||
| 22 | var _received_indexes = [] | ||
| 23 | var _received_items = {} | ||
| 24 | var _slot_data = {} | ||
| 25 | var _accessible_locations = [] | ||
| 26 | var _accessible_worldports = [] | ||
| 27 | var _goal_accessible = false | ||
| 28 | |||
| 29 | signal could_not_connect | ||
| 30 | signal connect_status | ||
| 31 | signal client_connected(slot_data) | ||
| 32 | signal item_received(item, amount) | ||
| 33 | signal location_scout_received(location_id, item_name, player_name, flags, for_self) | ||
| 34 | signal text_message_received(message) | ||
| 35 | signal item_sent_notification(message) | ||
| 36 | signal hint_received(message) | ||
| 37 | signal accessible_locations_updated | ||
| 38 | signal checked_locations_updated | ||
| 39 | signal checked_worldports_updated | ||
| 40 | signal keyboard_update_received | ||
| 41 | |||
| 42 | |||
| 43 | func _init(): | ||
| 44 | set_process_mode(Node.PROCESS_MODE_ALWAYS) | ||
| 45 | |||
| 46 | global._print("Instantiated APClient") | ||
| 47 | |||
| 48 | |||
| 49 | func _ready(): | ||
| 50 | _server = SCRIPT_websocketserver.new() | ||
| 51 | _server.client_connected.connect(_on_web_socket_server_client_connected) | ||
| 52 | _server.client_disconnected.connect(_on_web_socket_server_client_disconnected) | ||
| 53 | _server.message_received.connect(_on_web_socket_server_message_received) | ||
| 54 | add_child(_server) | ||
| 55 | _server.listen(43182) | ||
| 56 | |||
| 57 | |||
| 58 | func _reset_state(): | ||
| 59 | _should_process = false | ||
| 60 | _received_items = {} | ||
| 61 | _received_indexes = [] | ||
| 62 | _checked_worldports = [] | ||
| 63 | _accessible_locations = [] | ||
| 64 | _accessible_worldports = [] | ||
| 65 | _goal_accessible = false | ||
| 66 | |||
| 67 | |||
| 68 | func disconnect_from_ap(): | ||
| 69 | sendMessage([{"cmd": "Disconnect"}]) | ||
| 70 | |||
| 71 | |||
| 72 | func _on_web_socket_server_client_connected(peer_id: int) -> void: | ||
| 73 | var peer: WebSocketPeer = _server.peers[peer_id] | ||
| 74 | print("Remote client connected: %d. Protocol: %s" % [peer_id, peer.get_selected_protocol()]) | ||
| 75 | _server.send(-peer_id, "[%d] connected" % peer_id) | ||
| 76 | |||
| 77 | |||
| 78 | func _on_web_socket_server_client_disconnected(peer_id: int) -> void: | ||
| 79 | var peer: WebSocketPeer = _server.peers[peer_id] | ||
| 80 | print( | ||
| 81 | ( | ||
| 82 | "Remote client disconnected: %d. Code: %d, Reason: %s" | ||
| 83 | % [peer_id, peer.get_close_code(), peer.get_close_reason()] | ||
| 84 | ) | ||
| 85 | ) | ||
| 86 | _server.send(-peer_id, "[%d] disconnected" % peer_id) | ||
| 87 | |||
| 88 | |||
| 89 | func _on_web_socket_server_message_received(_peer_id: int, packet: String) -> void: | ||
| 90 | global._print("Got data from server: " + packet) | ||
| 91 | var json = JSON.new() | ||
| 92 | var jserror = json.parse(packet) | ||
| 93 | if jserror != OK: | ||
| 94 | global._print("Error parsing packet from AP: " + jserror.error_string) | ||
| 95 | return | ||
| 96 | |||
| 97 | for message in json.data: | ||
| 98 | var cmd = message["cmd"] | ||
| 99 | global._print("Received command: " + cmd) | ||
| 100 | |||
| 101 | if cmd == "Connected": | ||
| 102 | _seed = message["seed_name"] | ||
| 103 | _remote_version = message["version"] | ||
| 104 | _gen_version = message["generator_version"] | ||
| 105 | _team = message["team"] | ||
| 106 | _slot = message["slot"] | ||
| 107 | _slot_data = message["slot_data"] | ||
| 108 | |||
| 109 | _checked_locations = [] | ||
| 110 | for location in message["checked_locations"]: | ||
| 111 | _checked_locations.append(int(message["checked_locations"])) | ||
| 112 | |||
| 113 | client_connected.emit(_slot_data) | ||
| 114 | |||
| 115 | elif cmd == "ConnectionRefused": | ||
| 116 | could_not_connect.emit(message["text"]) | ||
| 117 | global._print("Connection to AP refused") | ||
| 118 | |||
| 119 | elif cmd == "UpdateLocations": | ||
| 120 | for location in message["locations"]: | ||
| 121 | var lint = int(location) | ||
| 122 | if not _checked_locations.has(lint): | ||
| 123 | _checked_locations.append(lint) | ||
| 124 | |||
| 125 | checked_locations_updated.emit() | ||
| 126 | |||
| 127 | elif cmd == "UpdateWorldports": | ||
| 128 | for port_id in message["worldports"]: | ||
| 129 | var lint = int(port_id) | ||
| 130 | if not _checked_worldports.has(lint): | ||
| 131 | _checked_worldports.append(lint) | ||
| 132 | |||
| 133 | checked_worldports_updated.emit() | ||
| 134 | |||
| 135 | elif cmd == "ItemReceived": | ||
| 136 | for item in message["items"]: | ||
| 137 | var index = int(item["index"]) | ||
| 138 | if _received_indexes.has(index): | ||
| 139 | # Do not re-process items. | ||
| 140 | continue | ||
| 141 | |||
| 142 | _received_indexes.append(index) | ||
| 143 | |||
| 144 | var item_id = int(item["id"]) | ||
| 145 | _received_items[item_id] = _received_items.get(item_id, 0) + 1 | ||
| 146 | |||
| 147 | item_received.emit(item, _received_items[item_id]) | ||
| 148 | |||
| 149 | elif cmd == "TextMessage": | ||
| 150 | text_message_received.emit(message["data"]) | ||
| 151 | |||
| 152 | elif cmd == "ItemSentNotif": | ||
| 153 | item_sent_notification.emit(message) | ||
| 154 | |||
| 155 | elif cmd == "HintReceived": | ||
| 156 | hint_received.emit(message) | ||
| 157 | |||
| 158 | elif cmd == "LocationInfo": | ||
| 159 | for loc in message["locations"]: | ||
| 160 | location_scout_received.emit( | ||
| 161 | int(loc["id"]), | ||
| 162 | loc["item"], | ||
| 163 | loc["player"], | ||
| 164 | int(loc["flags"]), | ||
| 165 | int(loc["for_self"]) | ||
| 166 | ) | ||
| 167 | |||
| 168 | elif cmd == "AccessibleLocations": | ||
| 169 | _accessible_locations.clear() | ||
| 170 | _accessible_worldports.clear() | ||
| 171 | |||
| 172 | for loc in message["locations"]: | ||
| 173 | _accessible_locations.append(int(loc)) | ||
| 174 | |||
| 175 | if "worldports" in message: | ||
| 176 | for port_id in message["worldports"]: | ||
| 177 | _accessible_worldports.append(int(port_id)) | ||
| 178 | |||
| 179 | _goal_accessible = bool(message.get("goal", false)) | ||
| 180 | |||
| 181 | accessible_locations_updated.emit() | ||
| 182 | |||
| 183 | elif cmd == "UpdateKeyboard": | ||
| 184 | var updates = {} | ||
| 185 | for k in message["updates"]: | ||
| 186 | updates[k] = int(message["updates"][k]) | ||
| 187 | |||
| 188 | keyboard_update_received.emit(updates) | ||
| 189 | |||
| 190 | |||
| 191 | func connectToServer(server, un, pw): | ||
| 192 | sendMessage([{"cmd": "Connect", "server": server, "player": un, "password": pw}]) | ||
| 193 | |||
| 194 | ap_server = server | ||
| 195 | ap_user = un | ||
| 196 | ap_pass = pw | ||
| 197 | |||
| 198 | _should_process = true | ||
| 199 | |||
| 200 | connect_status.emit("Connecting...") | ||
| 201 | |||
| 202 | |||
| 203 | func sendMessage(msg): | ||
| 204 | var payload = JSON.stringify(msg) | ||
| 205 | _server.send(0, payload) | ||
| 206 | |||
| 207 | |||
| 208 | func connectToRoom(): | ||
| 209 | connect_status.emit("Authenticating...") | ||
| 210 | |||
| 211 | sendMessage( | ||
| 212 | [ | ||
| 213 | { | ||
| 214 | "cmd": "Connect", | ||
| 215 | "password": ap_pass, | ||
| 216 | "game": "Lingo 2", | ||
| 217 | "name": ap_user, | ||
| 218 | } | ||
| 219 | ] | ||
| 220 | ) | ||
| 221 | |||
| 222 | |||
| 223 | func requestSync(): | ||
| 224 | sendMessage([{"cmd": "Sync"}]) | ||
| 225 | |||
| 226 | |||
| 227 | func sendLocation(loc_id): | ||
| 228 | sendMessage([{"cmd": "LocationChecks", "locations": [loc_id]}]) | ||
| 229 | |||
| 230 | |||
| 231 | func sendLocations(loc_ids): | ||
| 232 | sendMessage([{"cmd": "LocationChecks", "locations": loc_ids}]) | ||
| 233 | |||
| 234 | |||
| 235 | func say(textdata): | ||
| 236 | sendMessage([{"cmd": "Say", "text": textdata}]) | ||
| 237 | |||
| 238 | |||
| 239 | func completedGoal(): | ||
| 240 | sendMessage([{"cmd": "StatusUpdate", "status": 30}]) # CLIENT_GOAL | ||
| 241 | |||
| 242 | |||
| 243 | func scoutLocations(loc_ids): | ||
| 244 | sendMessage([{"cmd": "LocationScouts", "locations": loc_ids}]) | ||
| 245 | |||
| 246 | |||
| 247 | func updateKeyboard(updates): | ||
| 248 | sendMessage([{"cmd": "UpdateKeyboard", "keyboard": updates}]) | ||
| 249 | |||
| 250 | |||
| 251 | func checkWorldport(port_id): | ||
| 252 | if not _checked_worldports.has(port_id): | ||
| 253 | sendMessage([{"cmd": "CheckWorldport", "port_id": port_id}]) | ||
| 254 | |||
| 255 | |||
| 256 | func sendQuit(): | ||
| 257 | sendMessage([{"cmd": "Quit"}]) | ||
| 258 | |||
| 259 | |||
| 260 | func hasItem(item_id): | ||
| 261 | return _received_items.has(item_id) | ||
| 262 | |||
| 263 | |||
| 264 | func getItemAmount(item_id): | ||
| 265 | return _received_items.get(item_id, 0) | ||
