From 3f53502a5907ed1982d28a392c54331f0c1c2c42 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 25 Sep 2025 12:09:50 -0400 Subject: Move the client into the apworld Only works on source right now, not as an apworld. --- apworld/client/keyboard.gd | 199 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 apworld/client/keyboard.gd (limited to 'apworld/client/keyboard.gd') diff --git a/apworld/client/keyboard.gd b/apworld/client/keyboard.gd new file mode 100644 index 0000000..450566d --- /dev/null +++ b/apworld/client/keyboard.gd @@ -0,0 +1,199 @@ +extends Node + +const kALL_LETTERS = "abcdefghjiklmnopqrstuvwxyz" + +var letters_saved = {} +var letters_in_keyholders = [] +var letters_blocked = [] +var letters_dynamic = {} +var keyholder_state = {} + +var filename = "" + + +func _init(): + reset() + + +func reset(): + letters_saved.clear() + letters_in_keyholders.clear() + letters_blocked.clear() + letters_dynamic.clear() + keyholder_state.clear() + + +func load_seed(): + var ap = global.get_node("Archipelago") + + reset() + + filename = "user://archipelago_keys/%s_%d" % [ap.client._seed, ap.client._slot] + + if FileAccess.file_exists(filename): + var ap_file = FileAccess.open(filename, FileAccess.READ) + var localdata = [] + if ap_file != null: + localdata = ap_file.get_var(true) + ap_file.close() + + if typeof(localdata) != TYPE_ARRAY: + print("AP keyboard file is corrupted") + localdata = [] + + if localdata.size() > 0: + letters_saved = localdata[0] + if localdata.size() > 1: + letters_in_keyholders = localdata[1] + if localdata.size() > 2: + keyholder_state = localdata[2] + + for k in kALL_LETTERS: + var level = 0 + + if ap.get_letter_behavior(k, false) == ap.kLETTER_BEHAVIOR_UNLOCKED: + level += 1 + if ap.get_letter_behavior(k, true) == ap.kLETTER_BEHAVIOR_UNLOCKED: + level += 1 + + letters_dynamic[k] = level + + update_unlocks() + + +func save(): + var dir = DirAccess.open("user://") + var folder = "archipelago_keys" + if not dir.dir_exists(folder): + dir.make_dir(folder) + + var file = FileAccess.open(filename, FileAccess.WRITE) + + var data = [ + letters_saved, + letters_in_keyholders, + keyholder_state, + ] + file.store_var(data, true) + file.close() + + +func update_unlocks(): + unlocks.resetKeys() + + var has_doubles = false + + for k in kALL_LETTERS: + var level = 0 + + if not letters_in_keyholders.has(k): + level = letters_saved.get(k, 0) + letters_dynamic.get(k, 0) + + if level >= 2: + level = 2 + has_doubles = true + + if letters_blocked.has(k): + level = 0 + + unlocks.unlockKey(k, level) + + if has_doubles and unlocks.data["double_letters"] != "unlocked": + var ap = global.get_node("Archipelago") + if ap.cyan_door_behavior == ap.kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER: + unlocks.setData("double_letters", "unlocked") + + +func collect_local_letter(key, level): + if level < 0 or level > 2 or level < letters_saved.get(key, 0): + return + + letters_saved[key] = level + + if letters_blocked.has(key): + letters_blocked.erase(key) + + update_unlocks() + save() + + +func collect_remote_letter(key, level): + if level < 0 or level > 2 or level < letters_dynamic.get(key, 0): + return + + letters_dynamic[key] = level + + if letters_blocked.has(key): + letters_blocked.erase(key) + + update_unlocks() + save() + + +func put_in_keyholder(key, map, kh_path): + if not keyholder_state.has(map): + keyholder_state[map] = {} + + keyholder_state[map][kh_path] = key + letters_in_keyholders.append(key) + + get_tree().get_root().get_node("scene").get_node(kh_path).setFromAp( + key, min(letters_saved.get(key, 0) + letters_dynamic.get(key, 0), 2) + ) + + update_unlocks() + save() + + +func remove_from_keyholder(key, map, kh_path): + if not keyholder_state.has(map): + # This... shouldn't happen. + keyholder_state[map] = {} + + keyholder_state[map].erase(kh_path) + letters_in_keyholders.erase(key) + + get_tree().get_root().get_node("scene").get_node(kh_path).setFromAp(key, 0) + + update_unlocks() + save() + + +func block_letter(key): + if not letters_blocked.has(key): + letters_blocked.append(key) + + update_unlocks() + + +func load_keyholders(map): + if keyholder_state.has(map): + var khs = keyholder_state[map] + + for path in khs.keys(): + var key = khs[path] + get_tree().get_root().get_node("scene").get_node(path).setFromAp( + key, min(letters_saved.get(key, 0) + letters_dynamic.get(key, 0), 2) + ) + + +func reset_keyholders(): + if letters_in_keyholders.is_empty() and letters_blocked.is_empty(): + return false + + var cleared_anything = not letters_in_keyholders.is_empty() or not letters_blocked.is_empty() + + if keyholder_state.has(global.map): + for path in keyholder_state[global.map]: + get_tree().get_root().get_node("scene").get_node(path).setFromAp( + keyholder_state[global.map][path], 0 + ) + + keyholder_state.clear() + letters_in_keyholders.clear() + letters_blocked.clear() + + update_unlocks() + save() + + return cleared_anything -- cgit 1.4.1