about summary refs log tree commit diff stats
path: root/apworld/client/client.gd
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/client/client.gd')
-rw-r--r--apworld/client/client.gd265
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 @@
1extends Node
2
3const ap_version = {"major": 0, "minor": 6, "build": 3, "class": "Version"}
4
5var SCRIPT_websocketserver
6
7var _server
8var _should_process = false
9
10var _remote_version = {"major": 0, "minor": 0, "build": 0}
11var _gen_version = {"major": 0, "minor": 0, "build": 0}
12
13var ap_server = ""
14var ap_user = ""
15var ap_pass = ""
16
17var _seed = ""
18var _team = 0
19var _slot = 0
20var _checked_locations = []
21var _checked_worldports = []
22var _received_indexes = []
23var _received_items = {}
24var _slot_data = {}
25var _accessible_locations = []
26var _accessible_worldports = []
27var _goal_accessible = false
28
29signal could_not_connect
30signal connect_status
31signal client_connected(slot_data)
32signal item_received(item, amount)
33signal location_scout_received(location_id, item_name, player_name, flags, for_self)
34signal text_message_received(message)
35signal item_sent_notification(message)
36signal hint_received(message)
37signal accessible_locations_updated
38signal checked_locations_updated
39signal checked_worldports_updated
40signal keyboard_update_received
41
42
43func _init():
44 set_process_mode(Node.PROCESS_MODE_ALWAYS)
45
46 global._print("Instantiated APClient")
47
48
49func _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
58func _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
68func disconnect_from_ap():
69 sendMessage([{"cmd": "Disconnect"}])
70
71
72func _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
78func _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
89func _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
191func 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
203func sendMessage(msg):
204 var payload = JSON.stringify(msg)
205 _server.send(0, payload)
206
207
208func 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
223func requestSync():
224 sendMessage([{"cmd": "Sync"}])
225
226
227func sendLocation(loc_id):
228 sendMessage([{"cmd": "LocationChecks", "locations": [loc_id]}])
229
230
231func sendLocations(loc_ids):
232 sendMessage([{"cmd": "LocationChecks", "locations": loc_ids}])
233
234
235func say(textdata):
236 sendMessage([{"cmd": "Say", "text": textdata}])
237
238
239func completedGoal():
240 sendMessage([{"cmd": "StatusUpdate", "status": 30}]) # CLIENT_GOAL
241
242
243func scoutLocations(loc_ids):
244 sendMessage([{"cmd": "LocationScouts", "locations": loc_ids}])
245
246
247func updateKeyboard(updates):
248 sendMessage([{"cmd": "UpdateKeyboard", "keyboard": updates}])
249
250
251func checkWorldport(port_id):
252 if not _checked_worldports.has(port_id):
253 sendMessage([{"cmd": "CheckWorldport", "port_id": port_id}])
254
255
256func sendQuit():
257 sendMessage([{"cmd": "Quit"}])
258
259
260func hasItem(item_id):
261 return _received_items.has(item_id)
262
263
264func getItemAmount(item_id):
265 return _received_items.get(item_id, 0)