diff options
author | metamuffin <metamuffin@disroot.org> | 2025-09-15 23:46:37 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-09-15 23:46:37 +0200 |
commit | ebb5c295c03cb1689c081006ad2ee167bd355d0a (patch) | |
tree | 1d62a388a97bfb09e5a01b565b2bae53acd966ce /client | |
parent | 0b780e2271e63f10a2580afe9507d18d735527f8 (diff) | |
download | hurrycurry-ebb5c295c03cb1689c081006ad2ee167bd355d0a.tar hurrycurry-ebb5c295c03cb1689c081006ad2ee167bd355d0a.tar.bz2 hurrycurry-ebb5c295c03cb1689c081006ad2ee167bd355d0a.tar.zst |
move profile related functions to static Profile members
Diffstat (limited to 'client')
-rw-r--r-- | client/game.gd | 10 | ||||
-rw-r--r-- | client/global.gd | 88 | ||||
-rw-r--r-- | client/gui/components/message/item/item_message.gd | 2 | ||||
-rw-r--r-- | client/gui/menus/character.gd | 14 | ||||
-rw-r--r-- | client/gui/menus/main/play.gd | 12 | ||||
-rw-r--r-- | client/gui/menus/setup/setup.gd | 8 | ||||
-rw-r--r-- | client/gui/overlays/popup_message/popup_message.gd | 34 | ||||
-rw-r--r-- | client/profile.gd | 91 | ||||
-rw-r--r-- | client/profile.gd.uid | 1 | ||||
-rw-r--r-- | client/settings.gd | 9 |
10 files changed, 140 insertions, 129 deletions
diff --git a/client/game.gd b/client/game.gd index 76308349..a8f905fb 100644 --- a/client/game.gd +++ b/client/game.gd @@ -234,7 +234,7 @@ func handle_packet(p): if (player.is_customer and not Settings.read("gameplay.tutorial_disabled") and join_state == JoinState.JOINED): - var completed_ingredients: Array = Global.get_profile("tutorial_ingredients_played") + var completed_ingredients: Array = Profile.read("tutorial_ingredients_played") var completed := Global.array_has_all(completed_ingredients, ingredients) if not completed: @@ -301,11 +301,11 @@ func handle_packet(p): if p.success: var completed_item := ItemFactory.ParsedItem.new(item_names[p.item]) - var played: Array = Global.get_profile("tutorial_ingredients_played") + var played: Array = Profile.read("tutorial_ingredients_played") played.append(completed_item.name) played.append_array(completed_item.contents) - Global.set_profile("tutorial_ingredients_played", played) - Global.save_profile() + Profile.write("tutorial_ingredients_played", played) + Profile.save() while item_names[p.item] in tutorial_queue: tutorial_queue.erase(item_names[p.item]) @@ -372,7 +372,7 @@ func toggle_join(): match join_state: JoinState.SPECTATING: set_join_state(JoinState.WAITING) - mp.send_join(Global.get_profile("username"), Global.get_profile("character_style")) + mp.send_join(Profile.read("username"), Profile.read("character_style")) JoinState.WAITING: push_error("Join/Leave action already toggled.") JoinState.JOINED: diff --git a/client/global.gd b/client/global.gd index c7ee555e..d9d714aa 100644 --- a/client/global.gd +++ b/client/global.gd @@ -24,37 +24,9 @@ signal using_touch_change(using: bool) @warning_ignore("UNUSED_SIGNAL") signal hand_count_change(count: bool) -var default_profile := { - "username": "", - "character_style": { - "color": 0, - "headwear": 0, - "hairstyle": 0 - }, - "last_server_url": "", - "tutorial_ingredients_played": [], - "registry_asked": false, - "hints": { - "has_moved": false, - "has_boosted": false, - "has_interacted": false, - "has_rotated": false, - "has_reset": false, - "has_zoomed": false, - "has_seen_performance": false, - "has_seen_join_while_running": false - } -} - var using_joypad := false var using_touch := false -# profile and settings are stored in a Dictionary[String, Any] -var profile: Dictionary -var settings: Dictionary - -var settings_tree: GameSetting - var game_paused := false var hand_count := 0 @@ -68,7 +40,7 @@ var focused_node: Control var focused_menu: Menu # only use this as a last resort, currently exists to open setup menu from settings func _ready(): - profile = load_dict("user://profile", default_profile) + Profile.load("user://profile") Settings.load("user://settings.json") get_viewport().gui_focus_changed.connect(Sound.play_hover_maybe) get_viewport().gui_focus_changed.connect(func(node): focused_node = node) @@ -105,27 +77,6 @@ func _input(event): using_touch = false using_touch_change.emit(using_touch) -func save_profile(): - save_dict("user://profile", profile) - -func save_dict(path: String, dict: Dictionary): - var f = FileAccess.open(path, FileAccess.WRITE) - var to_save = dict.duplicate(true) - f.store_var(to_save, true) - -func load_dict(path: String, default: Dictionary) -> Dictionary: - # TOCTOU here. Godot docs says its fine. - if not FileAccess.file_exists(path): - print("Skip profile load") - return default - var f = FileAccess.open(path, FileAccess.READ) - var saved_dict = f.get_var(true) - - if saved_dict != null and saved_dict is Dictionary: - add_missing_keys(saved_dict, default) - - return saved_dict - func on_mobile() -> bool: var os_name := OS.get_name() return os_name == "Android" or os_name == "iOS" @@ -138,37 +89,6 @@ func on_high_end() -> bool: func on_vulkan() -> bool: return ProjectSettings.get_setting("rendering/rendering_device/driver") == "vulkan" -func get_profile(key: String): - if profile.has(key): - return profile[key] - else: - push_error("Tried to access profile setting \"%s\", which does not exist (missing key)" % key) - return null - -func set_profile(key: String, value): - if !profile.has(key): - push_error("Tried to set profile setting \"%s\", which does not yet exist (missing key)" % key) - return - if profile[key] != value: - profile[key] = value - -func set_hint(key: String, value: bool): - if !profile["hints"].has(key): - push_error("Tried to set hint \"%s\", which does not yet exist (missing key)" % key) - if profile["hints"][key] != value: - if value: - Settings.write("gameplay.hints_started", true) - Settings.save() - profile["hints"][key] = value - save_profile() # TODO avoid this call when bulk-unsetting hints - -func get_hint(key: String): - if profile["hints"].has(key): - return profile["hints"][key] - else: - push_error("Tried to access hint \"%s\", which does not exist (missing key)" % key) - return null - static func interpolate(current, target, dt): return target + (current - target) * exp(-dt) @@ -206,7 +126,7 @@ func language_list(): func array_eq(a, b): return a.all(func(e): return a.count(e) == b.count(e)) -func add_missing_keys(dict: Dictionary, reference: Dictionary): +static func add_missing_keys(dict: Dictionary, reference: Dictionary): for k in reference.keys(): if !dict.has(k) or typeof(dict[k]) != typeof(reference[k]): dict[k] = reference[k] @@ -220,8 +140,8 @@ func array_has_all(parent: Array, children: Array) -> bool: return false return true -func configure_viewport_aa(vp: Viewport, aa: String) -> void: - match aa: +func configure_viewport_aa(vp: Viewport) -> void: + match Settings.read("graphics.aa"): "disabled": vp.msaa_3d = Viewport.MSAA_DISABLED vp.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED diff --git a/client/gui/components/message/item/item_message.gd b/client/gui/components/message/item/item_message.gd index 4079e363..f5a97723 100644 --- a/client/gui/components/message/item/item_message.gd +++ b/client/gui/components/message/item/item_message.gd @@ -31,7 +31,7 @@ var timeout_initial := 0. @onready var v_box_container: VBoxContainer = $VBoxContainer func _ready() -> void: - Global.configure_viewport_aa(sub_viewport, Settings.read("graphics.aa")) + Global.configure_viewport_aa(sub_viewport) if enable_grayscale: sub_viewport_container.material = PRINTED_MAT diff --git a/client/gui/menus/character.gd b/client/gui/menus/character.gd index 3c1230ae..715a7b1f 100644 --- a/client/gui/menus/character.gd +++ b/client/gui/menus/character.gd @@ -22,8 +22,8 @@ extends Menu func _ready(): super() - $VBoxContainer/top_panel/a/username.text = Global.get_profile("username") - character.set_style(Global.get_profile("character_style"), "chef") + $VBoxContainer/top_panel/a/username.text = Profile.read("username") + character.set_style(Profile.read("character_style"), "chef") init_map() func init_map(): @@ -61,8 +61,8 @@ func exit(): popup_data.buttons = [accept_button] await submenu("res://gui/menus/popup.tscn", popup_data) return - Global.set_profile("username", username_edit.text) - Global.save_profile() + Profile.write("username", username_edit.text) + Profile.save() super() func _on_character_back_pressed(): @@ -90,7 +90,7 @@ func _on_hairstyle_forward_pressed() -> void: current_style.hairstyle = G.rem_euclid(current_style.hairstyle + 1, character.hairstyles.size())) func modify_style(modifier: Callable): - var current_style: Dictionary = Global.get_profile("character_style") + var current_style: Dictionary = Profile.read("character_style") modifier.call(current_style) - Global.set_profile("character_style", current_style) - character.set_style(Global.get_profile("character_style"), "chef") + Profile.write("character_style", current_style) + character.set_style(Profile.read("character_style"), "chef") diff --git a/client/gui/menus/main/play.gd b/client/gui/menus/main/play.gd index 87b0b5bf..1e64a02f 100644 --- a/client/gui/menus/main/play.gd +++ b/client/gui/menus/main/play.gd @@ -34,7 +34,7 @@ func _ready(): url_regex.compile("^(?:(ws|wss)://)?([^:]+)(?::([0-9]+))?$") if OS.has_feature("web"): server.hide() - connect_uri.text = Global.get_profile("last_server_url") + connect_uri.text = Profile.read("last_server_url") Sound.play_music("MainMenu") ServerList.update_server_list.connect(update_server_list) @@ -43,7 +43,7 @@ func _ready(): update_server_list_loading(ServerList.loading) super() - if not Global.get_profile("registry_asked"): + if not Profile.read("registry_asked"): var popup_data := MenuPopup.Data.new() popup_data.text = tr("c.menu.play.allow_query_registry").format([Settings.read("online.registry_url")]) var allow_button := Button.new() @@ -54,8 +54,8 @@ func _ready(): deny_button.pressed.connect(func(): Settings.write("online.use_registry", false)) popup_data.buttons = [allow_button, deny_button] await submenu("res://gui/menus/popup.tscn", popup_data) - Global.set_profile("registry_asked", true) - Global.save_profile() + Profile.write("registry_asked", true) + Profile.save() Settings.save() ServerList.start() @@ -110,8 +110,8 @@ func _on_connect_pressed(): if result.get_string(3) == "" and result.get_string(1) != "wss": url = url + ":27032" connect_uri.text = url - Global.set_profile("last_server_url", url) - Global.save_profile() + Profile.write("last_server_url", url) + Profile.save() connect_to(url) func _on_quick_connect_pressed(): diff --git a/client/gui/menus/setup/setup.gd b/client/gui/menus/setup/setup.gd index e4103603..878331ff 100644 --- a/client/gui/menus/setup/setup.gd +++ b/client/gui/menus/setup/setup.gd @@ -92,12 +92,12 @@ func _on_sign_pressed(): anim.play_backwards("paper_slide") await anim.animation_finished - Global.set_profile("username", username.text) - Global.set_profile("character_style", character_style) + Profile.write("username", username.text) + Profile.write("character_style", character_style) if skip_tutorial.button_pressed: for k in Global.profile["hints"].keys(): - Global.set_hint(k, true) - Global.save_profile() + Profile.set_hint(k, true) + Profile.save() Settings.write("gameplay.hints_started", skip_tutorial.button_pressed) Settings.write("gameplay.tutorial_disabled", skip_tutorial.button_pressed) diff --git a/client/gui/overlays/popup_message/popup_message.gd b/client/gui/overlays/popup_message/popup_message.gd index d577465b..6a3d8273 100644 --- a/client/gui/overlays/popup_message/popup_message.gd +++ b/client/gui/overlays/popup_message/popup_message.gd @@ -131,26 +131,26 @@ func stop_game_hints(): func _input(_event): if Input.is_action_just_pressed("boost"): - Global.set_hint("has_boosted", true) + Profile.set_hint("has_boosted", true) if any_action_just_pressed(["forwards", "backwards", "left", "right"]): - Global.set_hint("has_moved", true) + Profile.set_hint("has_moved", true) if any_action_just_pressed(["rotate_left", "rotate_right", "rotate_up", "rotate_down"]): - if not Global.get_hint("has_reset"): + if not Profile.get_hint("has_reset"): reset_timer.start() - Global.set_hint("has_rotated", true) + Profile.set_hint("has_rotated", true) if any_action_just_pressed(["zoom_in", "zoom_out"]): - Global.set_hint("has_zoomed", true) + Profile.set_hint("has_zoomed", true) if Input.is_action_just_pressed("interact_left") or Input.is_action_just_pressed("interact_right"): - Global.set_hint("has_interacted", true) + Profile.set_hint("has_interacted", true) if Input.is_action_just_pressed("reset"): - Global.set_hint("has_reset", true) + Profile.set_hint("has_reset", true) func _on_boost_timeout(): - if not Global.get_hint("has_boosted") and not Global.using_touch: + if not Profile.get_hint("has_boosted") and not Global.using_touch: display_hint_msg(tr("c.hint.boost").format([display_keybind("boost")])) func _on_move_timeout(): - if not Global.get_hint("has_moved") and not Global.using_touch: + if not Profile.get_hint("has_moved") and not Global.using_touch: display_hint_msg(tr("c.hint.movement").format([", ".join( [ display_keybind("forwards"), @@ -161,15 +161,15 @@ func _on_move_timeout(): )])) func _on_interact_timeout(): - if not Global.get_hint("has_interacted") and not Global.using_touch: + if not Profile.get_hint("has_interacted") and not Global.using_touch: display_hint_msg(tr("c.hint.interact").format([display_keybind("interact")])) func _on_reset_timeout(): - if not Global.get_hint("has_reset") and not Global.using_touch: + if not Profile.get_hint("has_reset") and not Global.using_touch: display_hint_msg(tr("c.hint.reset_camera").format([display_keybind("reset")])) func _on_zoom_timeout(): - if not Global.get_hint("has_zoomed") and not Global.using_touch: + if not Profile.get_hint("has_zoomed") and not Global.using_touch: display_hint_msg(tr("c.hint.zoom_camera").format([", ".join( [ display_keybind("zoom_in"), @@ -203,7 +203,7 @@ func any_action_just_pressed(actions: Array) -> bool: return false func _on_rotate_camera_timeout(): - if not Global.get_hint("has_rotated") and not Global.using_touch: + if not Profile.get_hint("has_rotated") and not Global.using_touch: display_hint_msg(tr("c.hint.rotate").format([", ".join( [ display_keybind("rotate_up"), @@ -214,13 +214,13 @@ func _on_rotate_camera_timeout(): )])) func _on_join_while_running_timeout(): - if not game.join_state == Game.JoinState.JOINED and not Global.get_hint("has_seen_join_while_running"): - Global.set_hint("has_seen_join_while_running", true) + if not game.join_state == Game.JoinState.JOINED and not Profile.get_hint("has_seen_join_while_running"): + Profile.set_hint("has_seen_join_while_running", true) display_hint_msg(tr("c.hint.join_while_running").format([display_keybind("menu")])) func _on_performance_timeout() -> void: - if not Global.get_hint("has_seen_performance") and Engine.get_frames_per_second() < DisplayServer.screen_get_refresh_rate() * 0.75: - Global.set_hint("has_seen_performance", true) + if not Profile.get_hint("has_seen_performance") and Engine.get_frames_per_second() < DisplayServer.screen_get_refresh_rate() * 0.75: + Profile.set_hint("has_seen_performance", true) display_hint_msg(tr("c.hint.framerate_low")) class PositionalMessage: diff --git a/client/profile.gd b/client/profile.gd new file mode 100644 index 00000000..438e8e66 --- /dev/null +++ b/client/profile.gd @@ -0,0 +1,91 @@ +# Hurry Curry! - a game about cooking +# Copyright (C) 2025 Hurry Curry! contributors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, version 3 of the License only. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +extends Node +class_name Profile + +static var default_profile := { + "username": "", + "character_style": { + "color": 0, + "headwear": 0, + "hairstyle": 0 + }, + "last_server_url": "", + "tutorial_ingredients_played": [], + "registry_asked": false, + "hints": { + "has_moved": false, + "has_boosted": false, + "has_interacted": false, + "has_rotated": false, + "has_reset": false, + "has_zoomed": false, + "has_seen_performance": false, + "has_seen_join_while_running": false + } +} + +# profile is stored in a Dictionary[String, Any] +static var values: Dictionary +static var loaded_path: String + +static func load(path: String): + # TOCTOU here. Godot docs says its fine. + if not FileAccess.file_exists(path): + print("Skip profile load") + return default_profile + var f = FileAccess.open(path, FileAccess.READ) + + values = f.get_var(true) + if values != null and values is Dictionary: + G.add_missing_keys(values, default_profile) + loaded_path = path + +static func save(): + var f = FileAccess.open(loaded_path, FileAccess.WRITE) + var to_save = values.duplicate(true) + f.store_var(to_save, true) + +static func read(key: String): + if values.has(key): + return values[key] + else: + push_error("Tried to access profile setting \"%s\", which does not exist (missing key)" % key) + return null + +static func write(key: String, value): + if !values.has(key): + push_error("Tried to set profile setting \"%s\", which does not yet exist (missing key)" % key) + return + if values[key] != value: + values[key] = value + +static func set_hint(key: String, value: bool): + if !values["hints"].has(key): + push_error("Tried to set hint \"%s\", which does not yet exist (missing key)" % key) + if values["hints"][key] != value: + if value: + Settings.write("gameplay.hints_started", true) + Settings.save() + values["hints"][key] = value + save() # TODO avoid this call when bulk-unsetting hints + +static func get_hint(key: String): + if values["hints"].has(key): + return values["hints"][key] + else: + push_error("Tried to access hint \"%s\", which does not exist (missing key)" % key) + return null diff --git a/client/profile.gd.uid b/client/profile.gd.uid new file mode 100644 index 00000000..5cd63b28 --- /dev/null +++ b/client/profile.gd.uid @@ -0,0 +1 @@ +uid://1hlvx8wuxl2d diff --git a/client/settings.gd b/client/settings.gd index 8381ddc2..55a2b90e 100644 --- a/client/settings.gd +++ b/client/settings.gd @@ -134,7 +134,7 @@ static func hook_changed_init(key: String, display: bool, callable: Callable): static func get_category_dict(prefix: String): var map = {} - for k in Global.settings.keys(): + for k in values.keys(): var kn = k.trim_prefix(prefix + ".") if kn == k: continue map[kn] = read(k) @@ -158,9 +158,8 @@ static var change_hooks_apply = { "audio.sfx_volume": h_volume_sfx, } -static func h_aa(mode): - var vp = Global.get_viewport() - Global.configure_viewport_aa(vp, mode) +static func h_aa(_mode): + Global.configure_viewport_aa(Global.get_viewport()) static func h_taa(enabled): Global.get_viewport().use_taa = enabled @@ -198,4 +197,4 @@ static func h_input(): static func h_hints_started(started: bool): if not started: for k in Global.profile["hints"].keys(): - Global.set_hint(k, false) + Profile.set_hint(k, false) |