about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Archipelago/client.gd70
-rw-r--r--Archipelago/doorControl.gd15
-rw-r--r--Archipelago/load.gd36
-rw-r--r--Archipelago/location.gd17
-rw-r--r--Archipelago/painting_eye.gd12
-rw-r--r--Archipelago/settings_screen.gd26
6 files changed, 176 insertions, 0 deletions
diff --git a/Archipelago/client.gd b/Archipelago/client.gd index 74fe6e9..cbddf89 100644 --- a/Archipelago/client.gd +++ b/Archipelago/client.gd
@@ -16,12 +16,21 @@ var _location_name_to_id = {}
16 16
17const uuid_util = preload("user://maps/Archipelago/vendor/uuid.gd") 17const uuid_util = preload("user://maps/Archipelago/vendor/uuid.gd")
18 18
19# TODO: caching per MW/slot, reset between connections
19var _authenticated = false 20var _authenticated = false
20var _team = 0 21var _team = 0
21var _slot = 0 22var _slot = 0
22var _players = [] 23var _players = []
23var _checked_locations = [] 24var _checked_locations = []
24var _slot_data = {} 25var _slot_data = {}
26var _door_ids_by_item = {}
27var _mentioned_doors = []
28var _painting_ids_by_item = {}
29var _mentioned_paintings = []
30var _panel_ids_by_location = {}
31
32var _map_loaded = false
33var _held_items = []
25 34
26signal client_connected 35signal client_connected
27 36
@@ -104,12 +113,36 @@ func _on_data():
104 _checked_locations = message["checked_locations"] 113 _checked_locations = message["checked_locations"]
105 _slot_data = message["slot_data"] 114 _slot_data = message["slot_data"]
106 115
116 if _slot_data.has("door_ids_by_item_id"):
117 _door_ids_by_item = _slot_data["door_ids_by_item_id"]
118
119 _mentioned_doors = []
120 for item in _door_ids_by_item.values():
121 for door in item:
122 _mentioned_doors.append(door)
123 if _slot_data.has("painting_ids_by_item_id"):
124 _painting_ids_by_item = _slot_data["painting_ids_by_item_id"]
125
126 _mentioned_paintings = []
127 for item in _painting_ids_by_item.values():
128 for painting in item:
129 _mentioned_paintings.append(painting)
130 if _slot_data.has("panel_ids_by_location_id"):
131 _panel_ids_by_location = _slot_data["panel_ids_by_location_id"]
132
107 emit_signal("client_connected") 133 emit_signal("client_connected")
108 134
109 elif cmd == "ConnectionRefused": 135 elif cmd == "ConnectionRefused":
110 global._print("Connection to AP refused") 136 global._print("Connection to AP refused")
111 global._print(message) 137 global._print(message)
112 138
139 elif cmd == "ReceivedItems":
140 for item in message["items"]:
141 if _map_loaded:
142 processItem(item["item"])
143 else:
144 _held_items.append(item["item"])
145
113 146
114func _process(_delta): 147func _process(_delta):
115 if _should_process: 148 if _should_process:
@@ -170,3 +203,40 @@ func connectToRoom():
170 } 203 }
171 ] 204 ]
172 ) 205 )
206
207
208func sendLocation(loc_id):
209 sendMessage([{"cmd": "LocationChecks", "locations": [loc_id]}])
210
211
212func mapFinishedLoading():
213 if !_map_loaded:
214 _map_loaded = true
215
216 for item in _held_items:
217 processItem(item)
218
219 _held_items = []
220
221
222func processItem(item):
223 global._print(item)
224
225 var stringified = String(item)
226 if _door_ids_by_item.has(stringified):
227 var doorsNode = get_tree().get_root().get_node("Spatial/Doors")
228 for door_id in _door_ids_by_item[stringified]:
229 doorsNode.get_node(door_id).openDoor()
230
231 if _painting_ids_by_item.has(stringified):
232 var paintingsNode = get_tree().get_root().get_node("Spatial/Decorations/Paintings")
233 for painting_id in _painting_ids_by_item[stringified]:
234 paintingsNode.get_node(painting_id).movePainting()
235
236
237func doorIsVanilla(door):
238 return !_mentioned_doors.has(door)
239
240
241func paintingIsVanilla(painting):
242 return !_mentioned_paintings.has(painting)
diff --git a/Archipelago/doorControl.gd b/Archipelago/doorControl.gd new file mode 100644 index 0000000..011b0e0 --- /dev/null +++ b/Archipelago/doorControl.gd
@@ -0,0 +1,15 @@
1extends "res://scripts/doorControl.gd"
2
3
4func handle_correct():
5 # TODO: Right now we are just assuming that door shuffle is on.
6 var apclient = global.get_node("Archipelago")
7 if apclient.doorIsVanilla(self.get_parent().name + "/" + self.name):
8 .handle_correct()
9
10
11func openDoor():
12 if !ran:
13 # Basically do the same thing that the base game does.
14 ran = true
15 $AnimationPlayer.play("Open")
diff --git a/Archipelago/load.gd b/Archipelago/load.gd new file mode 100644 index 0000000..b0ccafc --- /dev/null +++ b/Archipelago/load.gd
@@ -0,0 +1,36 @@
1extends "res://scripts/load.gd"
2
3
4func _load():
5 global._print("Hooked Load Start")
6
7 var apclient = global.get_node("Archipelago")
8
9 # TODO: Override the YOU panel with the AP slot name
10
11 # This is the best time to create the location nodes, since the map is now
12 # loaded but the panels haven't been solved from the save file yet.
13 var panels_parent = self.get_node("Panels")
14 var location_script = ResourceLoader.load("user://maps/Archipelago/location.gd")
15 for location_name in apclient._location_name_to_id:
16 var location = location_script.new()
17 location.ap_name = location_name
18 location.ap_id = apclient._location_name_to_id[location_name]
19 location.name = "AP_location_" + location.ap_id
20 self.add_child(location)
21
22 var panels = apclient._panel_ids_by_location[String(location.ap_id)]
23 location.total = panels.size()
24
25 for panel in panels:
26 var that_panel = panels_parent.get_node(panel)
27 that_panel.get_node("Viewport/GUI/Panel/TextEdit").connect(
28 "answer_correct", location, "handle_correct"
29 )
30
31 # Process any items received while the map was loading.
32 apclient.mapFinishedLoading()
33
34 # Proceed with the rest of the load.
35 global._print("Hooked Load End")
36 ._load()
diff --git a/Archipelago/location.gd b/Archipelago/location.gd new file mode 100644 index 0000000..b85b5c4 --- /dev/null +++ b/Archipelago/location.gd
@@ -0,0 +1,17 @@
1extends Node
2
3var ap_name = ""
4var ap_id = 0
5var total = 0
6var solved = 0
7var ran = false
8
9
10func handle_correct():
11 solved += 1
12
13 if solved >= total && !ran:
14 ran = true
15
16 var apclient = global.get_node("Archipelago")
17 apclient.sendLocation(ap_id)
diff --git a/Archipelago/painting_eye.gd b/Archipelago/painting_eye.gd new file mode 100644 index 0000000..86e0ce9 --- /dev/null +++ b/Archipelago/painting_eye.gd
@@ -0,0 +1,12 @@
1extends "res://scripts/painting_eye.gd"
2
3
4func _answer_correct():
5 # TODO: Right now we are just assuming that door shuffle is on.
6 var apclient = global.get_node("Archipelago")
7 if apclient.paintingIsVanilla(self.name):
8 ._answer_correct()
9
10
11func movePainting():
12 ._answer_correct()
diff --git a/Archipelago/settings_screen.gd b/Archipelago/settings_screen.gd index 0854a8b..9624693 100644 --- a/Archipelago/settings_screen.gd +++ b/Archipelago/settings_screen.gd
@@ -13,6 +13,11 @@ func _ready():
13 apclient_instance.name = "Archipelago" 13 apclient_instance.name = "Archipelago"
14 global.add_child(apclient_instance) 14 global.add_child(apclient_instance)
15 15
16 # Let's also inject any scripts we need to inject now.
17 installScriptExtension("user://maps/Archipelago/doorControl.gd")
18 installScriptExtension("user://maps/Archipelago/load.gd")
19 installScriptExtension("user://maps/Archipelago/painting_eye.gd")
20
16 global.get_node("Archipelago").connect("client_connected", self, "connectionSuccessful") 21 global.get_node("Archipelago").connect("client_connected", self, "connectionSuccessful")
17 22
18 # Populate textboxes with AP settings. 23 # Populate textboxes with AP settings.
@@ -21,6 +26,27 @@ func _ready():
21 self.get_node("Panel/password_box").text = global.get_node("Archipelago").ap_pass 26 self.get_node("Panel/password_box").text = global.get_node("Archipelago").ap_pass
22 27
23 28
29# Adapted from https://gitlab.com/Delta-V-Modding/Mods/-/blob/main/game/ModLoader.gd
30func installScriptExtension(childScriptPath: String):
31 var childScript = ResourceLoader.load(childScriptPath)
32
33 # Force Godot to compile the script now.
34 # We need to do this here to ensure that the inheritance chain is
35 # properly set up, and multiple mods can chain-extend the same
36 # class multiple times.
37 # This is also needed to make Godot instantiate the extended class
38 # when creating singletons.
39 # The actual instance is thrown away.
40 childScript.new()
41
42 var parentScript = childScript.get_base_script()
43 var parentScriptPath = parentScript.resource_path
44 global._print(
45 "ModLoader: Installing script extension: %s <- %s" % [parentScriptPath, childScriptPath]
46 )
47 childScript.take_over_path(parentScriptPath)
48
49
24func connectionSuccessful(): 50func connectionSuccessful():
25 # Switch to LL1 51 # Switch to LL1
26 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) 52 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)