about summary refs log tree commit diff stats
path: root/apworld/client/textclient.gd
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/client/textclient.gd')
-rw-r--r--apworld/client/textclient.gd310
1 files changed, 310 insertions, 0 deletions
diff --git a/apworld/client/textclient.gd b/apworld/client/textclient.gd new file mode 100644 index 0000000..530eddb --- /dev/null +++ b/apworld/client/textclient.gd
@@ -0,0 +1,310 @@
1extends CanvasLayer
2
3var tabs
4var panel
5var label
6var entry
7var tracker_label
8var is_open = false
9
10var locations_overlay
11var location_texture
12var worldport_texture
13var goal_texture
14
15var worldports_tab
16var worldports_tree
17var port_tree_item_by_map = {}
18var port_tree_item_by_map_port = {}
19
20
21func _ready():
22 process_mode = ProcessMode.PROCESS_MODE_ALWAYS
23 layer = 2
24
25 locations_overlay = RichTextLabel.new()
26 locations_overlay.name = "LocationsOverlay"
27 locations_overlay.offset_top = 220
28 locations_overlay.offset_bottom = 720
29 locations_overlay.offset_left = 20
30 locations_overlay.anchor_right = 1.0
31 locations_overlay.offset_right = -10
32 locations_overlay.scroll_active = false
33 locations_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
34 locations_overlay.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
35 add_child(locations_overlay)
36 update_locations_visibility()
37
38 tabs = TabContainer.new()
39 tabs.name = "Tabs"
40 tabs.offset_left = 100
41 tabs.offset_right = 1820
42 tabs.offset_top = 100
43 tabs.offset_bottom = 980
44 tabs.visible = false
45 tabs.theme = preload("res://assets/themes/baseUI.tres")
46 tabs.add_theme_font_size_override("font_size", 36)
47 add_child(tabs)
48
49 panel = MarginContainer.new()
50 panel.name = "Text Client"
51 panel.add_theme_constant_override("margin_top", 60)
52 panel.add_theme_constant_override("margin_left", 60)
53 panel.add_theme_constant_override("margin_right", 60)
54 panel.add_theme_constant_override("margin_bottom", 60)
55 tabs.add_child(panel)
56
57 label = RichTextLabel.new()
58 label.set_name("Label")
59 label.scroll_following = true
60 label.selection_enabled = true
61 label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
62 label.size_flags_vertical = Control.SIZE_EXPAND_FILL
63 label.push_font(preload("res://assets/fonts/Lingo2.ttf"))
64 label.push_font_size(36)
65
66 var entry_style = StyleBoxFlat.new()
67 entry_style.bg_color = Color(0.9, 0.9, 0.9, 1)
68
69 entry = LineEdit.new()
70 entry.set_name("Entry")
71 entry.add_theme_font_override("font", preload("res://assets/fonts/Lingo2.ttf"))
72 entry.add_theme_font_size_override("font_size", 36)
73 entry.add_theme_color_override("font_color", Color(0, 0, 0, 1))
74 entry.add_theme_color_override("cursor_color", Color(0, 0, 0, 1))
75 entry.add_theme_stylebox_override("focus", entry_style)
76 entry.text_submitted.connect(text_entered)
77
78 var tc_arranger = VBoxContainer.new()
79 tc_arranger.add_child(label)
80 tc_arranger.add_child(entry)
81 tc_arranger.add_theme_constant_override("separation", 40)
82 panel.add_child(tc_arranger)
83
84 var tracker_margins = MarginContainer.new()
85 tracker_margins.name = "Locations"
86 tracker_margins.add_theme_constant_override("margin_top", 60)
87 tracker_margins.add_theme_constant_override("margin_left", 60)
88 tracker_margins.add_theme_constant_override("margin_right", 60)
89 tracker_margins.add_theme_constant_override("margin_bottom", 60)
90 tabs.add_child(tracker_margins)
91
92 tracker_label = RichTextLabel.new()
93 tracker_margins.add_child(tracker_label)
94
95 worldports_tab = MarginContainer.new()
96 worldports_tab.name = "Worldports"
97 worldports_tab.add_theme_constant_override("margin_top", 60)
98 worldports_tab.add_theme_constant_override("margin_left", 60)
99 worldports_tab.add_theme_constant_override("margin_right", 60)
100 worldports_tab.add_theme_constant_override("margin_bottom", 60)
101 tabs.add_child(worldports_tab)
102 tabs.set_tab_hidden(2, true)
103
104 worldports_tree = Tree.new()
105 worldports_tree.columns = 2
106 worldports_tree.hide_root = true
107 worldports_tree.theme = preload("res://assets/themes/baseUI.tres")
108 worldports_tree.add_theme_font_size_override("font_size", 24)
109 worldports_tab.add_child(worldports_tree)
110
111 var runtime = global.get_node("Runtime")
112 var location_image = Image.new()
113 location_image.load_png_from_buffer(runtime.read_path("assets/location.png"))
114 location_texture = ImageTexture.create_from_image(location_image)
115
116 var worldport_image = Image.new()
117 worldport_image.load_png_from_buffer(runtime.read_path("assets/worldport.png"))
118 worldport_texture = ImageTexture.create_from_image(worldport_image)
119
120 var goal_image = Image.new()
121 goal_image.load_png_from_buffer(runtime.read_path("assets/goal.png"))
122 goal_texture = ImageTexture.create_from_image(goal_image)
123
124
125func _input(event):
126 if global.loaded and event is InputEventKey and event.pressed:
127 if event.keycode == KEY_TAB and !Input.is_key_pressed(KEY_SHIFT):
128 if !get_tree().paused:
129 is_open = true
130 get_tree().paused = true
131 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
132 tabs.visible = true
133 entry.grab_focus()
134 get_viewport().set_input_as_handled()
135 else:
136 dismiss()
137 elif event.keycode == KEY_ESCAPE:
138 if is_open:
139 dismiss()
140 get_viewport().set_input_as_handled()
141
142
143func dismiss():
144 if is_open:
145 get_tree().paused = false
146 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
147 tabs.visible = false
148 is_open = false
149
150
151func parse_printjson(text):
152 label.append_text("[p]" + text + "[/p]")
153
154
155func text_entered(text):
156 var ap = global.get_node("Archipelago")
157 var cmd = text.trim_suffix("\n")
158 entry.text = ""
159 if OS.is_debug_build():
160 if cmd.begins_with("/tp_map "):
161 var new_map = cmd.substr(8)
162 global.map = new_map
163 global.sets_entry_point = false
164 switcher.switch_map("res://objects/scenes/%s.tscn" % new_map)
165 return
166
167 ap.client.say(cmd)
168
169
170func update_locations():
171 var ap = global.get_node("Archipelago")
172 var gamedata = global.get_node("Gamedata")
173
174 tracker_label.clear()
175 tracker_label.push_font(preload("res://assets/fonts/Lingo2.ttf"))
176 tracker_label.push_font_size(24)
177
178 locations_overlay.clear()
179 locations_overlay.push_font(preload("res://assets/fonts/Lingo2.ttf"))
180 locations_overlay.push_font_size(24)
181 locations_overlay.push_color(Color(0.9, 0.9, 0.9, 1))
182 locations_overlay.push_outline_color(Color(0, 0, 0, 1))
183 locations_overlay.push_outline_size(2)
184
185 const kLocation = 0
186 const kWorldport = 1
187 const kGoal = 2
188
189 var location_names = []
190 var type_by_name = {}
191 for location_id in ap.client._accessible_locations:
192 if not ap.client._checked_locations.has(location_id):
193 var location_name = gamedata.location_name_by_id.get(location_id, "(Unknown)")
194 location_names.append(location_name)
195 type_by_name[location_name] = kLocation
196
197 for port_id in ap.client._accessible_worldports:
198 if not ap.client._checked_worldports.has(port_id):
199 var port_name = gamedata.get_worldport_display_name(port_id)
200 location_names.append(port_name)
201 type_by_name[port_name] = kWorldport
202
203 location_names.sort()
204
205 if ap.client._goal_accessible:
206 var location_name = gamedata.ending_display_name_by_name[ap.kEndingNameByVictoryValue[
207 ap.victory_condition
208 ]]
209 location_names.push_front(location_name)
210 type_by_name[location_name] = kGoal
211
212 var count = 0
213 for location_name in location_names:
214 tracker_label.append_text("[p]%s[/p]" % location_name)
215 if count < 18:
216 locations_overlay.push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT)
217 locations_overlay.append_text(location_name)
218 locations_overlay.append_text(" ")
219 if type_by_name[location_name] == kLocation:
220 locations_overlay.add_image(location_texture)
221 elif type_by_name[location_name] == kWorldport:
222 locations_overlay.add_image(worldport_texture)
223 elif type_by_name[location_name] == kGoal:
224 locations_overlay.add_image(goal_texture)
225 locations_overlay.pop()
226 count += 1
227
228 if count > 18:
229 locations_overlay.append_text("[p align=right][lb]...[rb][/p]")
230
231
232func update_locations_visibility():
233 var ap = global.get_node("Archipelago")
234 locations_overlay.visible = ap.show_locations
235
236
237func setup_worldports():
238 tabs.set_tab_hidden(2, false)
239
240 var root_ti = worldports_tree.create_item(null)
241
242 var ports_by_map_id = {}
243 var display_names_by_map_id = {}
244 var display_names_by_port_id = {}
245
246 var ap = global.get_node("Archipelago")
247 var gamedata = global.get_node("Gamedata")
248 for fpid in ap.port_pairings:
249 var port = gamedata.objects.get_ports()[fpid]
250 var room = gamedata.objects.get_rooms()[port.get_room_id()]
251
252 if not ports_by_map_id.has(room.get_map_id()):
253 ports_by_map_id[room.get_map_id()] = []
254
255 var map = gamedata.objects.get_maps()[room.get_map_id()]
256 display_names_by_map_id[map.get_id()] = map.get_display_name()
257
258 ports_by_map_id[room.get_map_id()].append(fpid)
259 display_names_by_port_id[fpid] = port.get_display_name()
260
261 var sorted_map_ids = ports_by_map_id.keys().duplicate()
262 sorted_map_ids.sort_custom(
263 func(a, b): return display_names_by_map_id[a] < display_names_by_map_id[b]
264 )
265
266 for map_id in sorted_map_ids:
267 var map_ti = root_ti.create_child()
268 map_ti.set_text(0, display_names_by_map_id[map_id])
269 map_ti.visible = false
270 map_ti.collapsed = true
271 port_tree_item_by_map[map_id] = map_ti
272 port_tree_item_by_map_port[map_id] = {}
273
274 var port_ids = ports_by_map_id[map_id]
275 port_ids.sort_custom(
276 func(a, b): return display_names_by_port_id[a] < display_names_by_port_id[b]
277 )
278
279 for port_id in port_ids:
280 var port_ti = map_ti.create_child()
281 port_ti.set_text(0, display_names_by_port_id[port_id])
282 port_ti.set_text(1, gamedata.get_worldport_display_name(ap.port_pairings[port_id]))
283 port_ti.visible = false
284 port_tree_item_by_map_port[map_id][port_id] = port_ti
285
286 update_worldports()
287
288
289func update_worldports():
290 var ap = global.get_node("Archipelago")
291
292 for map_id in port_tree_item_by_map_port.keys():
293 var map_visible = false
294
295 for port_id in port_tree_item_by_map_port[map_id].keys():
296 var ti = port_tree_item_by_map_port[map_id][port_id]
297 ti.visible = ap.client._checked_worldports.has(port_id)
298
299 if ti.visible:
300 map_visible = true
301
302 port_tree_item_by_map[map_id].visible = map_visible
303
304
305func reset():
306 locations_overlay.clear()
307 tabs.set_tab_hidden(2, true)
308 port_tree_item_by_map.clear()
309 port_tree_item_by_map_port.clear()
310 worldports_tree.clear()