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.gd308
1 files changed, 308 insertions, 0 deletions
diff --git a/apworld/client/main.gd b/apworld/client/main.gd new file mode 100644 index 0000000..c90d6e7 --- /dev/null +++ b/apworld/client/main.gd
@@ -0,0 +1,308 @@
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("saver.gd"))
52 installScriptExtension(runtime.load_script("teleport.gd"))
53 installScriptExtension(runtime.load_script("teleportListener.gd"))
54 installScriptExtension(runtime.load_script("unlockReaderListener.gd"))
55 installScriptExtension(runtime.load_script("visibilityListener.gd"))
56 installScriptExtension(runtime.load_script("worldport.gd"))
57 installScriptExtension(runtime.load_script("worldportListener.gd"))
58
59 var proto_script = runtime.load_script("../generated/proto.gd")
60 var gamedata_script = runtime.load_script("gamedata.gd")
61 var gamedata_instance = gamedata_script.new(proto_script)
62 gamedata_instance.load(runtime.read_path("../generated/data.binpb"))
63 gamedata_instance.name = "Gamedata"
64 global.add_child(gamedata_instance)
65
66 var messages_script = runtime.load_script("messages.gd")
67 var messages_instance = messages_script.new()
68 messages_instance.name = "Messages"
69 messages_instance.SCRIPT_rainbowText = runtime.load_script("rainbowText.gd")
70 global.add_child(messages_instance)
71
72 var effects_script = runtime.load_script("effects.gd")
73 var effects_instance = effects_script.new()
74 effects_instance.name = "Effects"
75 global.add_child(effects_instance)
76
77 var textclient_script = runtime.load_script("textclient.gd")
78 var textclient_instance = textclient_script.new()
79 textclient_instance.name = "Textclient"
80 global.add_child(textclient_instance)
81
82 var compass_overlay_script = runtime.load_script("compass_overlay.gd")
83 var compass_overlay_instance = compass_overlay_script.new()
84 compass_overlay_instance.name = "Compass"
85 compass_overlay_instance.SCRIPT_compass = runtime.load_script("compass.gd")
86 global.add_child(compass_overlay_instance)
87
88 unlocks.data["advanced_mastery"] = ""
89 unlocks.data["charismatic_mastery"] = ""
90 unlocks.data["crystalline_mastery"] = ""
91 unlocks.data["fuzzy_mastery"] = ""
92 unlocks.data["icarus_mastery"] = ""
93 unlocks.data["stellar_mastery"] = ""
94
95 var ap = global.get_node("Archipelago")
96 var gamedata = global.get_node("Gamedata")
97 ap.ap_connected.connect(connectionSuccessful)
98 ap.could_not_connect.connect(connectionUnsuccessful)
99 ap.connect_status.connect(connectionStatus)
100
101 # Populate textboxes with AP settings.
102 get_node("../Panel/server_box").text = ap.ap_server
103 get_node("../Panel/player_box").text = ap.ap_user
104 get_node("../Panel/password_box").text = ap.ap_pass
105
106 var history_box = get_node("../Panel/connection_history")
107 if ap.connection_history.is_empty():
108 history_box.disabled = true
109 else:
110 history_box.disabled = false
111
112 var i = 0
113 for details in ap.connection_history:
114 history_box.get_popup().add_item("%s (%s)" % [details[1], details[0]], i)
115 i += 1
116
117 history_box.get_popup().id_pressed.connect(historySelected)
118
119 # Show client version.
120 var version = gamedata.objects.get_version()
121 get_node("../Panel/title").text = (
122 "ARCHIPELAGO (%d.%d.%d)" % [version.get_major(), version.get_minor(), version.get_patch()]
123 )
124
125 # Increase font size in text boxes.
126 get_node("../Panel/server_box").add_theme_font_size_override("font_size", 36)
127 get_node("../Panel/player_box").add_theme_font_size_override("font_size", 36)
128 get_node("../Panel/password_box").add_theme_font_size_override("font_size", 36)
129
130 # Set up version mismatch dialog.
131 get_node("../Panel/VersionMismatch").confirmed.connect(startGame)
132 get_node("../Panel/VersionMismatch").get_cancel_button().pressed.connect(
133 versionMismatchDeclined
134 )
135
136 # Set up buttons.
137 get_node("../Panel/connect_button").pressed.connect(_connect_pressed)
138 get_node("../Panel/quit_button").pressed.connect(_back_pressed)
139
140
141func _connect_pressed():
142 get_node("../Panel/connect_button").disabled = true
143
144 var ap = global.get_node("Archipelago")
145 ap.ap_server = get_node("../Panel/server_box").text
146 ap.ap_user = get_node("../Panel/player_box").text
147 ap.ap_pass = get_node("../Panel/password_box").text
148 ap.saveSettings()
149
150 ap.connectToServer()
151
152
153func _back_pressed():
154 var ap = global.get_node("Archipelago")
155 ap.disconnect_from_ap()
156 ap.client.sendQuit()
157
158 get_tree().quit()
159
160
161# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd
162func installScriptExtension(childScript: Resource):
163 # Force Godot to compile the script now.
164 # We need to do this here to ensure that the inheritance chain is
165 # properly set up, and multiple mods can chain-extend the same
166 # class multiple times.
167 # This is also needed to make Godot instantiate the extended class
168 # when creating singletons.
169 # The actual instance is thrown away.
170 childScript.new()
171
172 var parentScript = childScript.get_base_script()
173 var parentScriptPath = parentScript.resource_path
174 global._print("ModLoader: Installing script extension over %s" % parentScriptPath)
175 childScript.take_over_path(parentScriptPath)
176
177
178func connectionStatus(message):
179 var popup = get_node("../Panel/AcceptDialog")
180 popup.title = "Connecting to Archipelago"
181 popup.dialog_text = message
182 popup.exclusive = true
183 popup.get_ok_button().visible = false
184 popup.popup_centered()
185
186
187func connectionSuccessful():
188 var ap = global.get_node("Archipelago")
189 var gamedata = global.get_node("Gamedata")
190
191 # Check for major version mismatch.
192 if ap.apworld_version[0] != gamedata.objects.get_version().get_major():
193 get_node("../Panel/AcceptDialog").exclusive = false
194
195 var popup = get_node("../Panel/VersionMismatch")
196 popup.title = "Version Mismatch!"
197 popup.dialog_text = (
198 "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."
199 % [
200 ap.apworld_version[0],
201 ap.apworld_version[1],
202 ap.apworld_version[2],
203 gamedata.objects.get_version().get_major(),
204 gamedata.objects.get_version().get_minor(),
205 gamedata.objects.get_version().get_patch()
206 ]
207 )
208 popup.exclusive = true
209 popup.popup_centered()
210
211 return
212
213 startGame()
214
215
216func startGame():
217 var ap = global.get_node("Archipelago")
218
219 # Save connection details
220 var connection_details = [ap.ap_server, ap.ap_user, ap.ap_pass]
221 if ap.connection_history.has(connection_details):
222 ap.connection_history.erase(connection_details)
223 ap.connection_history.push_front(connection_details)
224 if ap.connection_history.size() > 10:
225 ap.connection_history.resize(10)
226 ap.saveSettings()
227
228 # Switch to the_entry
229 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
230 global.user = ap.getSaveFileName()
231 global.universe = "lingo"
232 global.map = "the_entry"
233
234 unlocks.resetCollectables()
235 unlocks.resetData()
236 unlocks.loadCollectables()
237 unlocks.loadData()
238
239 ap.setup_keys()
240
241 unlocks.unlockKey("capslock", 1)
242
243 if ap.shuffle_worldports:
244 settings.worldport_fades = "default"
245 else:
246 settings.worldport_fades = "never"
247
248 clearResourceCache("res://objects/meshes/gridDoor.tscn")
249 clearResourceCache("res://objects/nodes/allowNumbers.tscn")
250 clearResourceCache("res://objects/nodes/collectable.tscn")
251 clearResourceCache("res://objects/nodes/door.tscn")
252 clearResourceCache("res://objects/nodes/keyHolder.tscn")
253 clearResourceCache("res://objects/nodes/listeners/animationListener.tscn")
254 clearResourceCache("res://objects/nodes/listeners/keyHolderChecker.tscn")
255 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn")
256 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn")
257 clearResourceCache("res://objects/nodes/listeners/unlockReaderListener.tscn")
258 clearResourceCache("res://objects/nodes/listeners/visibilityListener.tscn")
259 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn")
260 clearResourceCache("res://objects/nodes/panel.tscn")
261 clearResourceCache("res://objects/nodes/player.tscn")
262 clearResourceCache("res://objects/nodes/saver.tscn")
263 clearResourceCache("res://objects/nodes/teleport.tscn")
264 clearResourceCache("res://objects/nodes/worldport.tscn")
265 clearResourceCache("res://objects/scenes/menus/pause_menu.tscn")
266
267 var paintings_dir = DirAccess.open("res://objects/meshes/paintings")
268 if paintings_dir:
269 paintings_dir.list_dir_begin()
270 var file_name = paintings_dir.get_next()
271 while file_name != "":
272 if not paintings_dir.current_is_dir() and file_name.ends_with(".tscn"):
273 clearResourceCache("res://objects/meshes/paintings/" + file_name)
274 file_name = paintings_dir.get_next()
275
276 switcher.switch_map.call_deferred("res://objects/scenes/the_entry.tscn")
277
278
279func connectionUnsuccessful(error_message):
280 get_node("../Panel/connect_button").disabled = false
281
282 var popup = get_node("../Panel/AcceptDialog")
283 popup.title = "Could not connect to Archipelago"
284 popup.dialog_text = error_message
285 popup.exclusive = true
286 popup.get_ok_button().visible = true
287 popup.popup_centered()
288
289
290func versionMismatchDeclined():
291 get_node("../Panel/AcceptDialog").hide()
292 get_node("../Panel/connect_button").disabled = false
293
294 var ap = global.get_node("Archipelago")
295 ap.disconnect_from_ap()
296
297
298func historySelected(index):
299 var ap = global.get_node("Archipelago")
300 var details = ap.connection_history[index]
301
302 get_node("../Panel/server_box").text = details[0]
303 get_node("../Panel/player_box").text = details[1]
304 get_node("../Panel/password_box").text = details[2]
305
306
307func clearResourceCache(path):
308 ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE)