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