about summary refs log tree commit diff stats
path: root/apworld/client/main.gd
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/client/main.gd')
-rw-r--r--apworld/client/main.gd314
1 files changed, 314 insertions, 0 deletions
diff --git a/apworld/client/main.gd b/apworld/client/main.gd new file mode 100644 index 0000000..8cac24c --- /dev/null +++ b/apworld/client/main.gd
@@ -0,0 +1,314 @@
1extends Node
2
3
4func _ready():
5 var runtime = global.get_node("Runtime")
6
7 # Some helpful logging.
8 if Steam.isSubscribed():
9 global._print("Provisioning successful! Build ID: %d" % Steam.getAppBuildId())
10 else:
11 global._print("Provisioning failed.")
12
13 # Undo the load screen removing our cursor
14 get_tree().get_root().set_disable_input(false)
15 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
16
17 # Increase the WebSocket input buffer size so that we can download large
18 # data packages.
19 ProjectSettings.set_setting("network/limits/websocket_client/max_in_buffer_kb", 8192)
20
21 switcher.layer = 4
22
23 # Create the global AP manager, if it doesn't already exist.
24 if not global.has_node("Archipelago"):
25 var ap_script = runtime.load_script("manager.gd")
26 var ap_instance = ap_script.new()
27 ap_instance.name = "Archipelago"
28
29 ap_instance.SCRIPT_client = runtime.load_script("client.gd")
30 ap_instance.SCRIPT_keyboard = runtime.load_script("keyboard.gd")
31 ap_instance.SCRIPT_locationListener = runtime.load_script("locationListener.gd")
32 ap_instance.SCRIPT_minimap = runtime.load_script("minimap.gd")
33 ap_instance.SCRIPT_victoryListener = runtime.load_script("victoryListener.gd")
34 ap_instance.SCRIPT_websocketserver = runtime.load_script("vendor/WebSocketServer.gd")
35
36 global.add_child(ap_instance)
37
38 # Let's also inject any scripts we need to inject now.
39 installScriptExtension(runtime.load_script("allowNumbers.gd"))
40 installScriptExtension(runtime.load_script("animationListener.gd"))
41 installScriptExtension(runtime.load_script("collectable.gd"))
42 installScriptExtension(runtime.load_script("door.gd"))
43 installScriptExtension(runtime.load_script("keyHolder.gd"))
44 installScriptExtension(runtime.load_script("keyHolderChecker.gd"))
45 installScriptExtension(runtime.load_script("keyHolderResetterListener.gd"))
46 installScriptExtension(runtime.load_script("painting.gd"))
47 installScriptExtension(runtime.load_script("paintingAuto.gd"))
48 installScriptExtension(runtime.load_script("panel.gd"))
49 installScriptExtension(runtime.load_script("pauseMenu.gd"))
50 installScriptExtension(runtime.load_script("player.gd"))
51 installScriptExtension(runtime.load_script("rteMenu.gd"))
52 installScriptExtension(runtime.load_script("saver.gd"))
53 installScriptExtension(runtime.load_script("teleport.gd"))
54 installScriptExtension(runtime.load_script("teleportListener.gd"))
55 installScriptExtension(runtime.load_script("unlockReaderListener.gd"))
56 installScriptExtension(runtime.load_script("visibilityListener.gd"))
57 installScriptExtension(runtime.load_script("worldport.gd"))
58 installScriptExtension(runtime.load_script("worldportListener.gd"))
59
60 var proto_script = runtime.load_script("../generated/proto.gd")
61 var gamedata_script = runtime.load_script("gamedata.gd")
62 var gamedata_instance = gamedata_script.new(proto_script)
63 gamedata_instance.load(runtime.read_path("../generated/data.binpb"))
64 gamedata_instance.name = "Gamedata"
65 global.add_child(gamedata_instance)
66
67 var messages_script = runtime.load_script("messages.gd")
68 var messages_instance = messages_script.new()
69 messages_instance.name = "Messages"
70 messages_instance.SCRIPT_rainbowText = runtime.load_script("rainbowText.gd")
71 global.add_child(messages_instance)
72
73 var effects_script = runtime.load_script("effects.gd")
74 var effects_instance = effects_script.new()
75 effects_instance.name = "Effects"
76 global.add_child(effects_instance)
77
78 var textclient_script = runtime.load_script("textclient.gd")
79 var textclient_instance = textclient_script.new()
80 textclient_instance.name = "Textclient"
81 global.add_child(textclient_instance)
82
83 var compass_overlay_script = runtime.load_script("compass_overlay.gd")
84 var compass_overlay_instance = compass_overlay_script.new()
85 compass_overlay_instance.name = "Compass"
86 compass_overlay_instance.SCRIPT_compass = runtime.load_script("compass.gd")
87 global.add_child(compass_overlay_instance)
88
89 unlocks.data["advanced_mastery"] = ""
90 unlocks.data["charismatic_mastery"] = ""
91 unlocks.data["crystalline_mastery"] = ""
92 unlocks.data["fuzzy_mastery"] = ""
93 unlocks.data["icarus_mastery"] = ""
94 unlocks.data["stellar_mastery"] = ""
95
96 var ap = global.get_node("Archipelago")
97 var gamedata = global.get_node("Gamedata")
98 ap.ap_connected.connect(connectionSuccessful)
99 ap.could_not_connect.connect(connectionUnsuccessful)
100 ap.connect_status.connect(connectionStatus)
101
102 # Populate textboxes with AP settings.
103 get_node("../Panel/server_box").text = ap.ap_server
104 get_node("../Panel/player_box").text = ap.ap_user
105 get_node("../Panel/password_box").text = ap.ap_pass
106
107 var history_box = get_node("../Panel/connection_history")
108 if ap.connection_history.is_empty():
109 history_box.disabled = true
110 else:
111 history_box.disabled = false
112
113 var i = 0
114 for details in ap.connection_history:
115 history_box.get_popup().add_item("%s (%s)" % [details[1], details[0]], i)
116 i += 1
117
118 history_box.get_popup().id_pressed.connect(historySelected)
119
120 # Show client version.
121 var version = gamedata.objects.get_version()
122 get_node("../Panel/title").text = (
123 "ARCHIPELAGO (%d.%d.%d)" % [version.get_major(), version.get_minor(), version.get_patch()]
124 )
125
126 # Increase font size in text boxes.
127 get_node("../Panel/server_box").add_theme_font_size_override("font_size", 36)
128 get_node("../Panel/player_box").add_theme_font_size_override("font_size", 36)
129 get_node("../Panel/password_box").add_theme_font_size_override("font_size", 36)
130
131 # Set up version mismatch dialog.
132 get_node("../Panel/VersionMismatch").confirmed.connect(startGame)
133 get_node("../Panel/VersionMismatch").get_cancel_button().pressed.connect(
134 versionMismatchDeclined
135 )
136
137 # Set up buttons.
138 get_node("../Panel/connect_button").pressed.connect(_connect_pressed)
139 get_node("../Panel/quit_button").pressed.connect(_back_pressed)
140
141
142func _connect_pressed():
143 get_node("../Panel/connect_button").disabled = true
144
145 var ap = global.get_node("Archipelago")
146 ap.ap_server = get_node("../Panel/server_box").text
147 ap.ap_user = get_node("../Panel/player_box").text
148 ap.ap_pass = get_node("../Panel/password_box").text
149 ap.saveSettings()
150
151 ap.connectToServer()
152
153
154func _back_pressed():
155 var ap = global.get_node("Archipelago")
156 ap.disconnect_from_ap()
157 ap.client.sendQuit()
158
159 get_tree().quit()
160
161
162# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd
163func installScriptExtension(childScript: Resource):
164 # Force Godot to compile the script now.
165 # We need to do this here to ensure that the inheritance chain is
166 # properly set up, and multiple mods can chain-extend the same
167 # class multiple times.
168 # This is also needed to make Godot instantiate the extended class
169 # when creating singletons.
170 # The actual instance is thrown away.
171 childScript.new()
172
173 var parentScript = childScript.get_base_script()
174 var parentScriptPath = parentScript.resource_path
175 global._print("ModLoader: Installing script extension over %s" % parentScriptPath)
176 childScript.take_over_path(parentScriptPath)
177
178
179func connectionStatus(message):
180 var popup = get_node("../Panel/AcceptDialog")
181 popup.title = "Connecting to Archipelago"
182 popup.dialog_text = message
183 popup.exclusive = true
184 popup.get_ok_button().visible = false
185 popup.popup_centered()
186
187
188func connectionSuccessful():
189 var ap = global.get_node("Archipelago")
190 var gamedata = global.get_node("Gamedata")
191
192 # Check for major version mismatch.
193 if ap.apworld_version[0] != gamedata.objects.get_version().get_major():
194 get_node("../Panel/AcceptDialog").exclusive = false
195
196 var popup = get_node("../Panel/VersionMismatch")
197 popup.title = "Version Mismatch!"
198 popup.dialog_text = (
199 "This slot was generated using v%d.%d.%d of the Lingo 2 apworld,\nwhich has a different major version than this client (v%d.%d.%d).\nIt is highly recommended to play using the correct version of the client.\nYou may experience bugs or logic issues if you continue."
200 % [
201 ap.apworld_version[0],
202 ap.apworld_version[1],
203 ap.apworld_version[2],
204 gamedata.objects.get_version().get_major(),
205 gamedata.objects.get_version().get_minor(),
206 gamedata.objects.get_version().get_patch()
207 ]
208 )
209 popup.exclusive = true
210 popup.popup_centered()
211
212 return
213
214 startGame()
215
216
217func startGame():
218 var ap = global.get_node("Archipelago")
219
220 # Save connection details
221 var connection_details = [ap.ap_server, ap.ap_user, ap.ap_pass]
222 if ap.connection_history.has(connection_details):
223 ap.connection_history.erase(connection_details)
224 ap.connection_history.push_front(connection_details)
225 if ap.connection_history.size() > 10:
226 ap.connection_history.resize(10)
227 ap.saveSettings()
228
229 # Switch to the_entry
230 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
231 global.user = ap.getSaveFileName()
232 global.universe = "lingo"
233
234 if ap.daedalus_only:
235 global.map = "daedalus"
236 else:
237 global.map = "the_entry"
238
239 unlocks.resetCollectables()
240 unlocks.resetData()
241 unlocks.loadCollectables()
242 unlocks.loadData()
243
244 ap.setup_keys()
245
246 unlocks.unlockKey("capslock", 1)
247
248 if ap.shuffle_worldports:
249 settings.worldport_fades = "default"
250 else:
251 settings.worldport_fades = "never"
252
253 clearResourceCache("res://objects/meshes/gridDoor.tscn")
254 clearResourceCache("res://objects/nodes/allowNumbers.tscn")
255 clearResourceCache("res://objects/nodes/collectable.tscn")
256 clearResourceCache("res://objects/nodes/door.tscn")
257 clearResourceCache("res://objects/nodes/keyHolder.tscn")
258 clearResourceCache("res://objects/nodes/listeners/animationListener.tscn")
259 clearResourceCache("res://objects/nodes/listeners/keyHolderChecker.tscn")
260 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn")
261 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn")
262 clearResourceCache("res://objects/nodes/listeners/unlockReaderListener.tscn")
263 clearResourceCache("res://objects/nodes/listeners/visibilityListener.tscn")
264 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn")
265 clearResourceCache("res://objects/nodes/panel.tscn")
266 clearResourceCache("res://objects/nodes/player.tscn")
267 clearResourceCache("res://objects/nodes/saver.tscn")
268 clearResourceCache("res://objects/nodes/teleport.tscn")
269 clearResourceCache("res://objects/nodes/worldport.tscn")
270 clearResourceCache("res://objects/scenes/menus/pause_menu.tscn")
271 clearResourceCache("res://objects/scenes/menus/rte_inner.tscn")
272
273 var paintings_dir = DirAccess.open("res://objects/meshes/paintings")
274 if paintings_dir:
275 paintings_dir.list_dir_begin()
276 var file_name = paintings_dir.get_next()
277 while file_name != "":
278 if not paintings_dir.current_is_dir() and file_name.ends_with(".tscn"):
279 clearResourceCache("res://objects/meshes/paintings/" + file_name)
280 file_name = paintings_dir.get_next()
281
282 switcher.switch_map.call_deferred("res://objects/scenes/%s.tscn" % global.map)
283
284
285func connectionUnsuccessful(error_message):
286 get_node("../Panel/connect_button").disabled = false
287
288 var popup = get_node("../Panel/AcceptDialog")
289 popup.title = "Could not connect to Archipelago"
290 popup.dialog_text = error_message
291 popup.exclusive = true
292 popup.get_ok_button().visible = true
293 popup.popup_centered()
294
295
296func versionMismatchDeclined():
297 get_node("../Panel/AcceptDialog").hide()
298 get_node("../Panel/connect_button").disabled = false
299
300 var ap = global.get_node("Archipelago")
301 ap.disconnect_from_ap()
302
303
304func historySelected(index):
305 var ap = global.get_node("Archipelago")
306 var details = ap.connection_history[index]
307
308 get_node("../Panel/server_box").text = details[0]
309 get_node("../Panel/player_box").text = details[1]
310 get_node("../Panel/password_box").text = details[2]
311
312
313func clearResourceCache(path):
314 ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE)