diff options
Diffstat (limited to 'client/gui/menus/main')
-rw-r--r-- | client/gui/menus/main/about.gd | 169 | ||||
-rw-r--r-- | client/gui/menus/main/about.gd.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/about.tscn | 93 | ||||
-rw-r--r-- | client/gui/menus/main/background.gd | 50 | ||||
-rw-r--r-- | client/gui/menus/main/background.gd.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/background.tscn | 71 | ||||
-rw-r--r-- | client/gui/menus/main/clouds.gdshader | 36 | ||||
-rw-r--r-- | client/gui/menus/main/clouds.gdshader.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/main.gd | 44 | ||||
-rw-r--r-- | client/gui/menus/main/main.gd.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/main.tscn | 94 | ||||
-rw-r--r-- | client/gui/menus/main/play.gd | 208 | ||||
-rw-r--r-- | client/gui/menus/main/play.gd.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/play.tscn | 149 | ||||
-rw-r--r-- | client/gui/menus/main/server_list_item.gd | 38 | ||||
-rw-r--r-- | client/gui/menus/main/server_list_item.gd.uid | 1 | ||||
-rw-r--r-- | client/gui/menus/main/server_list_item.tscn | 39 |
17 files changed, 997 insertions, 0 deletions
diff --git a/client/gui/menus/main/about.gd b/client/gui/menus/main/about.gd new file mode 100644 index 00000000..b56d3941 --- /dev/null +++ b/client/gui/menus/main/about.gd @@ -0,0 +1,169 @@ +# 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 Menu + +var authors := ["metamuffin", "nokoe", "tpart"] +var contributors := ["sofviic", "BigBrotherNii", "Miner34"] +const cc_by_4 := "CC-BY 4.0" +const cc_by_3 := "CC-BY 3.0" +const cc0 := "CC0" + +const AGPL_NOTICE := """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/>.""" + +const SOURCE_CODE := "https://codeberg.org/hurrycurry/hurrycurry" + +func _ready() -> void: + super() + $side/margin/options/first/source.tooltip_text = SOURCE_CODE + +var credits := [ + [tr("c.credits.models"), [ + ["kenney.nl", "Various Models", cc0], + ["Kay Lousberg", "Kitchen tiles", cc0], + ["Poly by Google", "Strawberry", cc_by_3], + ["Poly by Google", "Fish", cc_by_3], + ["jeremy", "Propeller hat", cc_by_3] + ]], + [tr("c.credits.sounds"), [ + ["Dryoma", "Footstep sounds", cc_by_4], + ["Koops", "Page_Turn_24.wav", cc_by_4], + ["InspectorJ", "Pencil, Writing, Close, A.wav", cc_by_4], + ["Dillon Becker", "Super Dialogue Audio Pack", cc_by_4], + ["Ellr", "Universal UI/Menu Soundpack", cc_by_4], + ["toyoto", "Woosh Fleuret Escrime B.wav", cc_by_4], + ["deleted_user_877451", "Game_over.wav", cc_by_3], + ["Quaternius", "Someting, dont remember...", cc0], + ["Dillon Becker", "Super Dialogue Audio Pack V1", cc_by_4] + ]], + [tr("c.credits.translations"), { + tr("c.settings.ui.language.zh_Hans"): ["Outbreak2096"], + tr("c.settings.ui.language.zh_Hant"): ["hugoalh"], + tr("c.settings.ui.language.nl"): ["Vistaus"], + tr("c.settings.ui.language.it"): ["Miner34", "solemden"], + tr("c.settings.ui.language.eu"): ["josuigoa"], + tr("c.settings.ui.language.fr"): ["fnetX", "lejun"], + tr("c.settings.ui.language.pl"): ["tranzystorekk"], + tr("c.settings.ui.language.he"): ["RustyStriker"], + tr("c.settings.ui.language.el"): ["n0toose"], + tr("c.settings.ui.language.ja"): ["BigBrotherNii"], + tr("c.settings.ui.language.ar"): ["sofviic"], + tr("c.settings.ui.language.tr"): ["furkanunsalan", "tekrei"], + tr("c.settings.ui.language.ru"): ["0ko"], + }] +] + +func _menu_cover(state): + $side.visible = not state + +func credits_text() -> String: + var text = "[center]" + authors.shuffle() + contributors.shuffle() + + text += "\n\n\n[b]%s[/b]\n\n%s\n\n[b]%s[/b]\n\n%s\n\n[b]%s[/b]\n\n\n" % [ + tr("c.credits.title"), + tr("c.credits.developed_by"), + "\n".join(authors), + tr("c.credits.contributors"), + ", ".join(contributors), + ] + + for section in credits: + text += "[b]%s[/b]\n\n" % section[0] + if typeof(section[1]) == TYPE_DICTIONARY: + text += "[table=2]" + for key in section[1]: + text += "[cell][right]%s[/right][/cell]" % key + text += "[cell][left]%s[/left][/cell]" % ", ".join(section[1][key]) + text += "[/table]" + else: + text += "[table=3]" + for entry in section[1]: + text += "[cell][right]%s[/right][/cell]" % entry[0] + text += "[cell][left]%s[/left][/cell]" % entry[1] + text += "[cell][left]%s[/left][/cell]" % entry[2] + text += "[/table]" + text += "\n\n\n" + + text += "\n[b]%s[/b]\n\n\n[/center]" % tr("c.credits.thanks") + return text + +func legal_text() -> String: + var all: Array[String] = [] + var translators: Array[String] = [] + for c in credits[2][1].values(): + translators.append_array(c) + translators.shuffle() + authors.shuffle() + contributors.shuffle() + all.append_array(authors) + all.append_array(contributors) + all.append_array(translators) + + var text := "Hurry Curry! - a game about cooking\n" + text += "[code]Copyright 2024, 2025 %s\n\n" % ", ".join(dedup_array(all)) + text += "%s[/code]\n\n" % AGPL_NOTICE + text += tr("c.legal.using_godot") + text += "\n\n[code]%s[/code]" % Engine.get_license_text() + return text + +func version_text() -> String: + var text := "[center][b]Hurry Curry![/b]\n\n" + OS.get_version() + text += "[table=2]" + var row = "[cell][right]%s[/right][/cell][cell][left]%s[/left][/cell]" + text += row % [tr("c.version.game"), Global.VERSION] + text += row % [tr("c.version.protocol"), "%s.%s" % [Multiplayer.VERSION_MAJOR, Multiplayer.VERSION_MINOR]] + text += row % [tr("c.version.godot"), Engine.get_version_info().string] + text += row % [tr("c.version.os"), OS.get_name()] + text += row % [tr("c.version.arch"), Engine.get_architecture_name()] + text += row % [tr("c.version.distribution"), Global.DISTRIBUTION] + + text += "[/table]" + text += "[/center]" + return text + +func _on_credits_pressed() -> void: + submenu("res://gui/menus/popup_large.tscn", credits_text()) + +func _on_legal_pressed() -> void: + submenu("res://gui/menus/popup_large.tscn", legal_text()) + +func _on_version_pressed() -> void: + submenu("res://gui/menus/popup_large.tscn", version_text()) + +func _on_back_pressed() -> void: + exit() + + +func _on_source_pressed() -> void: + OS.shell_open(SOURCE_CODE) + +func dedup_array(a: Array) -> Array: + var b = [] + for x in a: if not b.has(x): b.append(x) + return b diff --git a/client/gui/menus/main/about.gd.uid b/client/gui/menus/main/about.gd.uid new file mode 100644 index 00000000..3929f2c3 --- /dev/null +++ b/client/gui/menus/main/about.gd.uid @@ -0,0 +1 @@ +uid://pcu87stpkgd8 diff --git a/client/gui/menus/main/about.tscn b/client/gui/menus/main/about.tscn new file mode 100644 index 00000000..006b61fe --- /dev/null +++ b/client/gui/menus/main/about.tscn @@ -0,0 +1,93 @@ +[gd_scene load_steps=7 format=3 uid="uid://bpaenm8c6nmo8"] + +[ext_resource type="Script" uid="uid://pcu87stpkgd8" path="res://gui/menus/main/about.gd" id="1_0acu0"] +[ext_resource type="Material" uid="uid://2j8a0c0a2ta5" path="res://gui/resources/materials/blur_material.tres" id="1_ai5pk"] +[ext_resource type="StyleBox" uid="uid://bw4jamyna1top" path="res://gui/resources/style/panel_style_sidebar.tres" id="2_pya1x"] +[ext_resource type="FontFile" uid="uid://bo4vh5xkpvrh1" path="res://gui/resources/fonts/font-sansita-swashed.woff2" id="4_kx3j7"] +[ext_resource type="Script" uid="uid://byshs20og68tn" path="res://gui/components/smart_margin_container.gd" id="4_t51wf"] + +[sub_resource type="FontVariation" id="FontVariation_o2r3e"] +base_font = ExtResource("4_kx3j7") +variation_embolden = 0.5 + +[node name="AboutMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_0acu0") +support_anim = false + +[node name="side" type="PanelContainer" parent="."] +material = ExtResource("1_ai5pk") +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 294.0 +grow_vertical = 2 +theme_override_styles/panel = ExtResource("2_pya1x") + +[node name="margin" type="MarginContainer" parent="side"] +layout_mode = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 +script = ExtResource("4_t51wf") + +[node name="options" type="VBoxContainer" parent="side/margin"] +layout_mode = 2 + +[node name="title" type="Label" parent="side/margin/options"] +auto_translate_mode = 2 +layout_mode = 2 +theme_override_colors/font_outline_color = Color(0.566408, 0.208917, 0.266045, 1) +theme_override_constants/outline_size = 10 +theme_override_fonts/font = SubResource("FontVariation_o2r3e") +theme_override_font_sizes/font_size = 48 +text = "Hurry Curry!" + +[node name="spacer" type="Control" parent="side/margin/options"] +custom_minimum_size = Vector2(0, 10) +layout_mode = 2 + +[node name="first" type="VBoxContainer" parent="side/margin/options"] +layout_mode = 2 + +[node name="credits" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.about.credits" +alignment = 0 + +[node name="version" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.about.version" +alignment = 0 + +[node name="legal" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.about.legal" +alignment = 0 + +[node name="source" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.about.source" +alignment = 0 + +[node name="first2" type="VBoxContainer" parent="side/margin/options"] +layout_mode = 2 +size_flags_vertical = 3 +alignment = 2 + +[node name="back" type="Button" parent="side/margin/options/first2"] +layout_mode = 2 +text = "c.menu.back" +alignment = 0 + +[connection signal="pressed" from="side/margin/options/first/credits" to="." method="_on_credits_pressed"] +[connection signal="pressed" from="side/margin/options/first/version" to="." method="_on_version_pressed"] +[connection signal="pressed" from="side/margin/options/first/legal" to="." method="_on_legal_pressed"] +[connection signal="pressed" from="side/margin/options/first/source" to="." method="_on_source_pressed"] +[connection signal="pressed" from="side/margin/options/first2/back" to="." method="_on_back_pressed"] diff --git a/client/gui/menus/main/background.gd b/client/gui/menus/main/background.gd new file mode 100644 index 00000000..4abb84b4 --- /dev/null +++ b/client/gui/menus/main/background.gd @@ -0,0 +1,50 @@ +# 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 Node3D + +const CRATES = ["tomato-crate", "steak-crate", "cheese-crate", "lettuce-crate", "flour-crate", "coconut-crate"] +const TOOLS = ["stove", "stove", "stove", "sink", "cuttingboard", "sink", "cuttingboard", "oven", "freezer"] + +@onready var environment: WorldEnvironment = $Environment +@onready var map: Map = $Map + +func _ready(): + if !Global.on_vulkan(): + environment.environment.tonemap_exposure = 0.25 + + var tiles = {} + for x in range(-10, 11): + for y in range(-10, 11): + var w = exp(-sqrt(x * x + y * y) * 0.15) + var k = randf() * w + var tn = null + if k > 0.25: tn = "floor" + if k > 0.4: tn = choose(CRATES) if randf() > 0.3 else "counter" + if k > 0.6: tn = choose(TOOLS) + if tn != null: tiles[str(Vector2i(x,y))] = [tn,[x,y]] + + var gt = func (cs): + var t = tiles.get(str(Vector2i(cs[0],cs[1]))) + return null if t == null else t[0] + for pk in tiles.keys(): + var x = tiles[pk][1][0] + var y = tiles[pk][1][1] + var t = gt.call([x,y]) + if t != null: map.set_tile(Vector2i(x,y), t, [[x,y-1],[x-1,y],[x,y+1],[x+1,y]].map(gt)) + + map.flush() + +func choose(a): return a[floor(a.size() * randf())] diff --git a/client/gui/menus/main/background.gd.uid b/client/gui/menus/main/background.gd.uid new file mode 100644 index 00000000..7d61d488 --- /dev/null +++ b/client/gui/menus/main/background.gd.uid @@ -0,0 +1 @@ +uid://b2tq5rcjjcxdg diff --git a/client/gui/menus/main/background.tscn b/client/gui/menus/main/background.tscn new file mode 100644 index 00000000..2bd4ee04 --- /dev/null +++ b/client/gui/menus/main/background.tscn @@ -0,0 +1,71 @@ +[gd_scene load_steps=12 format=3 uid="uid://l4vm07dtda4j"] + +[ext_resource type="Script" uid="uid://b2tq5rcjjcxdg" path="res://gui/menus/main/background.gd" id="1_pgu7b"] +[ext_resource type="Script" uid="uid://cwg7wympevxs4" path="res://map/auto_setup/environment_setup.gd" id="2_7dwbj"] +[ext_resource type="Shader" uid="uid://b1k6ipo0sagli" path="res://gui/menus/main/clouds.gdshader" id="3_lapmn"] +[ext_resource type="PackedScene" uid="uid://b4gone8fu53r7" path="res://map/map.tscn" id="4_nslxb"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_uw50b"] +sky_top_color = Color(0.55, 0.55, 0.55, 1) + +[sub_resource type="Sky" id="Sky_utrtx"] +sky_material = SubResource("ProceduralSkyMaterial_uw50b") + +[sub_resource type="Environment" id="Environment_slkjl"] +background_mode = 1 +background_color = Color(0.517035, 0.49506, 0.878906, 1) +sky = SubResource("Sky_utrtx") +tonemap_mode = 2 +tonemap_exposure = 0.6 +tonemap_white = 0.9 +ssao_enabled = true + +[sub_resource type="QuadMesh" id="QuadMesh_fvp2p"] +size = Vector2(100, 100) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_e3eby"] +noise_type = 2 +frequency = 0.008 +fractal_octaves = 7 +fractal_gain = 0.72 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_s4fnp"] +width = 1024 +height = 1024 +generate_mipmaps = false +seamless = true +noise = SubResource("FastNoiseLite_e3eby") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_gd87g"] +render_priority = 0 +shader = ExtResource("3_lapmn") +shader_parameter/noise = SubResource("NoiseTexture2D_s4fnp") +shader_parameter/ccloud = Color(0.835938, 0.835938, 0.835938, 1) +shader_parameter/csky = Color(0.329412, 0.333333, 0.8, 1) + +[node name="MenuBackground" type="Node3D"] +script = ExtResource("1_pgu7b") + +[node name="Camera" type="Camera3D" parent="."] +transform = Transform3D(0.614606, 0.499662, -0.610408, -0.00282255, 0.775198, 0.631712, 0.78883, -0.386531, 0.477852, -9.13611, 4.90356, 1.22532) +projection = 1 +current = true +size = 8.0 +far = 100.0 + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.290334, 0.904946, -0.311092, 0.336606, 0.207739, 0.918445, 0.895769, -0.371371, -0.244296, 0, 7, 0) +light_energy = 1.25 +shadow_enabled = true + +[node name="Environment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_slkjl") +script = ExtResource("2_7dwbj") +allow_sdfgi = false + +[node name="the-sky-tm" type="MeshInstance3D" parent="."] +transform = Transform3D(0.614606, 0.499662, -0.610408, -0.00282255, 0.775198, 0.631712, 0.78883, -0.386531, 0.477851, 6, -13, -11) +mesh = SubResource("QuadMesh_fvp2p") +surface_material_override/0 = SubResource("ShaderMaterial_gd87g") + +[node name="Map" parent="." instance=ExtResource("4_nslxb")] diff --git a/client/gui/menus/main/clouds.gdshader b/client/gui/menus/main/clouds.gdshader new file mode 100644 index 00000000..8103f691 --- /dev/null +++ b/client/gui/menus/main/clouds.gdshader @@ -0,0 +1,36 @@ +/* + 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/>. + +*/ +shader_type spatial; +render_mode unshaded; + +uniform sampler2D noise : source_color; +uniform vec3 ccloud : source_color; +uniform vec3 csky : source_color; + +void fragment() { + vec2 uv = UV * 0.9; + uv += TIME * vec2(0.001,0.002); + + float f = texture(noise, uv).x; + f = 1. - f; + f = pow(f, 1.5); + f = floor(f*5.)/5.; + f = pow(f, 2.); + + ALBEDO = mix(csky, ccloud, f); +} diff --git a/client/gui/menus/main/clouds.gdshader.uid b/client/gui/menus/main/clouds.gdshader.uid new file mode 100644 index 00000000..00c2d21a --- /dev/null +++ b/client/gui/menus/main/clouds.gdshader.uid @@ -0,0 +1 @@ +uid://b1k6ipo0sagli diff --git a/client/gui/menus/main/main.gd b/client/gui/menus/main/main.gd new file mode 100644 index 00000000..423f756e --- /dev/null +++ b/client/gui/menus/main/main.gd @@ -0,0 +1,44 @@ +# 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 Menu + +@onready var quit_button = $side/margin/options/first/quit +@onready var margin_container: MarginContainer = $side/margin + +func _ready(): + super() + if OS.has_feature("web"): + quit_button.hide() + Sound.play_music("MainMenu") + ServerList.one_shot() + +func _menu_cover(state): + $side.visible = not state + +func _on_quit_pressed(): + quit() + +func _on_about_pressed(): + submenu("res://gui/menus/main/about.tscn") + +func _on_change_character_pressed(): + replace_menu("res://gui/menus/character.tscn", null, "res://gui/menus/main.tscn") + +func _on_settings_pressed(): + submenu("res://gui/menus/settings/settings.tscn") + +func _on_play_pressed(): + submenu("res://gui/menus/main/play.tscn") diff --git a/client/gui/menus/main/main.gd.uid b/client/gui/menus/main/main.gd.uid new file mode 100644 index 00000000..dc2cecd3 --- /dev/null +++ b/client/gui/menus/main/main.gd.uid @@ -0,0 +1 @@ +uid://bpiynadrmdd37 diff --git a/client/gui/menus/main/main.tscn b/client/gui/menus/main/main.tscn new file mode 100644 index 00000000..81595966 --- /dev/null +++ b/client/gui/menus/main/main.tscn @@ -0,0 +1,94 @@ +[gd_scene load_steps=10 format=3 uid="uid://dbj8508whxgwv"] + +[ext_resource type="Theme" uid="uid://b0qmvo504e457" path="res://gui/resources/theme/theme.tres" id="1_3qfu3"] +[ext_resource type="Script" uid="uid://bpiynadrmdd37" path="res://gui/menus/main/main.gd" id="2_xjnc3"] +[ext_resource type="PackedScene" uid="uid://l4vm07dtda4j" path="res://gui/menus/main/background.tscn" id="3_4evao"] +[ext_resource type="Material" uid="uid://2j8a0c0a2ta5" path="res://gui/resources/materials/blur_material.tres" id="4_nx4vf"] +[ext_resource type="Script" uid="uid://cmncjc06kadpe" path="res://gui/components/blur_setup.gd" id="5_0mn56"] +[ext_resource type="FontFile" uid="uid://bo4vh5xkpvrh1" path="res://gui/resources/fonts/font-sansita-swashed.woff2" id="5_k7bqq"] +[ext_resource type="StyleBox" uid="uid://bw4jamyna1top" path="res://gui/resources/style/panel_style_sidebar.tres" id="5_qlyeo"] +[ext_resource type="Script" uid="uid://byshs20og68tn" path="res://gui/components/smart_margin_container.gd" id="7_btdj1"] + +[sub_resource type="FontVariation" id="FontVariation_htgmg"] +base_font = ExtResource("5_k7bqq") +variation_embolden = 0.5 + +[node name="MainMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_3qfu3") +script = ExtResource("2_xjnc3") + +[node name="MenuBackground" parent="." instance=ExtResource("3_4evao")] + +[node name="side" type="PanelContainer" parent="."] +material = ExtResource("4_nx4vf") +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 294.0 +grow_vertical = 2 +theme_override_styles/panel = ExtResource("5_qlyeo") +script = ExtResource("5_0mn56") + +[node name="margin" type="MarginContainer" parent="side"] +layout_mode = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 +script = ExtResource("7_btdj1") + +[node name="options" type="VBoxContainer" parent="side/margin"] +layout_mode = 2 + +[node name="title" type="Label" parent="side/margin/options"] +auto_translate_mode = 2 +layout_mode = 2 +theme_override_colors/font_outline_color = Color(0.566408, 0.208917, 0.266045, 1) +theme_override_constants/outline_size = 10 +theme_override_fonts/font = SubResource("FontVariation_htgmg") +theme_override_font_sizes/font_size = 48 +text = "Hurry Curry!" + +[node name="spacer" type="Control" parent="side/margin/options"] +custom_minimum_size = Vector2(0, 10) +layout_mode = 2 + +[node name="first" type="VBoxContainer" parent="side/margin/options"] +layout_mode = 2 + +[node name="play" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.play" +alignment = 0 + +[node name="change_character" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.my_chef" +alignment = 0 + +[node name="settings" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.settings" +alignment = 0 + +[node name="about" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.about" +alignment = 0 + +[node name="quit" type="Button" parent="side/margin/options/first"] +layout_mode = 2 +text = "c.menu.quit" +alignment = 0 + +[connection signal="pressed" from="side/margin/options/first/play" to="." method="_on_play_pressed"] +[connection signal="pressed" from="side/margin/options/first/change_character" to="." method="_on_change_character_pressed"] +[connection signal="pressed" from="side/margin/options/first/settings" to="." method="_on_settings_pressed"] +[connection signal="pressed" from="side/margin/options/first/about" to="." method="_on_about_pressed"] +[connection signal="pressed" from="side/margin/options/first/quit" to="." method="_on_quit_pressed"] diff --git a/client/gui/menus/main/play.gd b/client/gui/menus/main/play.gd new file mode 100644 index 00000000..c9cbee2f --- /dev/null +++ b/client/gui/menus/main/play.gd @@ -0,0 +1,208 @@ +# 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 Menu + +var server_list_item: PackedScene = preload("res://gui/menus/main/server_list_item.tscn") +var url_regex: RegEx = RegEx.new() + +@onready var server_list: VBoxContainer = $side/margin/options/second/ScrollContainerCustom/ServerList +@onready var server_list_loading: Label = $side/margin/options/second/Loading +@onready var server_list_empty: Label = $side/margin/options/second/NoServers +@onready var connect_uri = $side/margin/options/second/connect/uri +@onready var server = $side/margin/options/second/server +@onready var server_control = $side/margin/options/second/server/control +@onready var server_connect = $side/margin/options/second/server/connect +@onready var editor_control = $side/margin/options/second/editor/control +@onready var editor_connect = $side/margin/options/second/editor/connect +@onready var editor_container = $side/margin/options/second/editor + + +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") + Sound.play_music("MainMenu") + + ServerList.update_server_list.connect(update_server_list) + ServerList.update_loading.connect(update_server_list_loading) + update_server_list(ServerList.current_list) + update_server_list_loading(ServerList.loading) + + super() + if not Global.get_profile("registry_asked"): + var popup_data := MenuPopup.Data.new() + popup_data.text = tr("c.menu.play.allow_query_registry").format([Global.get_setting("online.registry_url")]) + var allow_button := Button.new() + allow_button.text = tr("c.menu.accept") + var deny_button := Button.new() + deny_button.text = tr("c.menu.deny") + allow_button.pressed.connect(func(): Global.set_setting("online.use_registry", true)) + deny_button.pressed.connect(func(): Global.set_setting("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_settings() + Global.save_profile() + + ServerList.start() + +func update_server_list(lists: Array[Array]): + # Find out the index of the currently focused server in the list + var prev_selected_idx := -1 + for i in range(server_list.get_children().size()): + if server_list.get_child(i).button.has_focus(): + prev_selected_idx = i + break + + for c in server_list.get_children(): + c.queue_free() + + var idx := 0 + for l in lists: + for i in l: + var server_item: ServerListItem = server_list_item.instantiate() + server_list.add_child(server_item) + # TODO: Implement fallback address correctly + server_item.setup(i.name, roundi(i.players_online), i.version) + server_item.button.pressed.connect(connect_to.bind(i.address[0])) + # Focus the same server with the same index as the previously focused one + if idx == prev_selected_idx: + server_item.button.grab_focus() + idx += 1 + + if prev_selected_idx > idx: + # Same index cannot be focused, since number of servers decreased + if idx - 1 < 0: + connect_uri.grab_focus() + else: + server_list.get_child(idx - 1).button.grab_focus() + + # Show message if no servers available + server_list_empty.visible = idx == 0 + +func update_server_list_loading(status: bool): + server_list_loading.visible = status + +func _menu_cover(state): + $side.visible = not state + +func _on_connect_pressed(): + var url = connect_uri.text + var result := url_regex.search(url) + if result != null: + if result.get_string(1) == "": + url = "ws://" + url + # only set default port for non-tls websocket connections + 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() + connect_to(url) + +func _on_quick_connect_pressed(): + if OS.has_feature("web"): + connect_to(JavaScriptBridge.eval(""" + window.location.protocol.endsWith("s:") + ? `wss://${window.location.host}/` + : `ws://${window.location.hostname}:27032/` + """)) + else: + connect_to("wss://hurrycurry.metamuffin.org/") + +func connect_to(url: String): + print("Connecting to %s" % url) + get_parent().replace_menu("res://gui/menus/game.tscn", url) + +func _on_server_control_pressed(): + match Server.state: + Service.State.RUNNING: Server.stop() + Service.State.STOPPED: Server.start() + Service.State.FAILED: Server.start() + +func _on_editor_control_pressed(): + match Editor.state: + Service.State.RUNNING: Editor.stop() + Service.State.STOPPED: Editor.start(); Server.start() + Service.State.FAILED: Editor.start() + +func _on_server_connect_pressed(): + connect_to("ws://%s:%d" % [Server.connect_address(), Global.get_setting("server.bind_port")]) + +func _on_editor_connect_pressed(): + connect_to("ws://[::1]:27032/") + +func _process(_delta): + server_control.disabled = false + server_connect.visible = Server.state == Service.State.RUNNING + server_control.modulate = Color.WHITE + match Server.state: + Service.State.RUNNING: + server_control.text = tr("c.menu.play.server_stop") + server_control.modulate = Color.AQUAMARINE + Service.State.TESTING: + server_control.text = tr("c.menu.play.server_testing") + server_control.disabled = true + Service.State.STARTING: + server_control.text = tr("c.menu.play.server_starting") + server_control.disabled = true + Service.State.STOPPED: + server_control.text = tr("c.menu.play.server_start") + Service.State.FAILED: + server_control.text = tr("c.menu.play.server_failed") + server_control.modulate = Color(1, 0.4, 0.5) + server_control.tooltip_text = tr("c.menu.play.server_failed_tooltip") + Service.State.UNAVAILABLE: + server_control.text = tr("c.menu.play.server_unavailable") + server_control.disabled = true + server_control.tooltip_text = tr("c.menu.play.server_binary_not_found") + + editor_control.disabled = false + editor_connect.visible = Editor.state == Service.State.RUNNING + editor_control.modulate = Color.WHITE + editor_container.visible = Editor.state != Service.State.UNAVAILABLE + match Editor.state: + Service.State.RUNNING: + editor_control.text = tr("c.menu.play.editor_stop") + editor_control.modulate = Color.AQUAMARINE + Service.State.TESTING: + editor_control.text = tr("c.menu.play.editor_testing") + editor_control.disabled = true + Service.State.STARTING: + editor_control.text = tr("c.menu.play.editor_starting") + editor_control.disabled = true + Service.State.STOPPED: + editor_control.text = tr("c.menu.play.editor_start") + Service.State.FAILED: + editor_control.text = tr("c.menu.play.editor_failed") + editor_control.modulate = Color(1, 0.4, 0.5) + editor_control.tooltip_text = tr("c.menu.play.server_failed_tooltip") + Service.State.UNAVAILABLE: + editor_control.text = tr("c.menu.play.editor_unavailable") + editor_control.disabled = true + editor_control.tooltip_text = tr("c.menu.play.server_binary_not_found") + + +func _on_uri_text_changed(new_text): + connect_uri.modulate = Color.WHITE if url_regex.search(new_text) else Color.RED + +func _on_back_pressed(): + exit() + +func _menu_exit(): + ServerList.stop() + super() diff --git a/client/gui/menus/main/play.gd.uid b/client/gui/menus/main/play.gd.uid new file mode 100644 index 00000000..d8ca168f --- /dev/null +++ b/client/gui/menus/main/play.gd.uid @@ -0,0 +1 @@ +uid://b126k2228nj4s diff --git a/client/gui/menus/main/play.tscn b/client/gui/menus/main/play.tscn new file mode 100644 index 00000000..441024a2 --- /dev/null +++ b/client/gui/menus/main/play.tscn @@ -0,0 +1,149 @@ +[gd_scene load_steps=9 format=3 uid="uid://c8url5fpttbem"] + +[ext_resource type="Theme" uid="uid://b0qmvo504e457" path="res://gui/resources/theme/theme.tres" id="1_cckds"] +[ext_resource type="Script" uid="uid://b126k2228nj4s" path="res://gui/menus/main/play.gd" id="2_phxx0"] +[ext_resource type="Material" uid="uid://2j8a0c0a2ta5" path="res://gui/resources/materials/blur_material.tres" id="3_fsbt7"] +[ext_resource type="Script" uid="uid://byshs20og68tn" path="res://gui/components/smart_margin_container.gd" id="4_gst6r"] +[ext_resource type="Script" uid="uid://bd7bylb2t2m0" path="res://gui/components/touch_scroll_container.gd" id="5_cm120"] +[ext_resource type="FontFile" uid="uid://bo4vh5xkpvrh1" path="res://gui/resources/fonts/font-sansita-swashed.woff2" id="5_ojpbf"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ukani"] + +[sub_resource type="FontVariation" id="FontVariation_htgmg"] +base_font = ExtResource("5_ojpbf") +variation_embolden = 0.5 + +[node name="PlayMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_cckds") +script = ExtResource("2_phxx0") +support_anim = false + +[node name="side" type="PanelContainer" parent="."] +material = ExtResource("3_fsbt7") +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 294.0 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_ukani") + +[node name="margin" type="MarginContainer" parent="side"] +layout_mode = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 +script = ExtResource("4_gst6r") + +[node name="options" type="VBoxContainer" parent="side/margin"] +layout_mode = 2 + +[node name="title" type="Label" parent="side/margin/options"] +auto_translate_mode = 2 +layout_mode = 2 +theme_override_colors/font_outline_color = Color(0.566408, 0.208917, 0.266045, 1) +theme_override_constants/outline_size = 10 +theme_override_fonts/font = SubResource("FontVariation_htgmg") +theme_override_font_sizes/font_size = 48 +text = "Hurry Curry!" + +[node name="spacer" type="Control" parent="side/margin/options"] +custom_minimum_size = Vector2(0, 10) +layout_mode = 2 + +[node name="second" type="VBoxContainer" parent="side/margin/options"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Loading" type="Label" parent="side/margin/options/second"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +text = "c.menu.play.fetching_list" +horizontal_alignment = 1 + +[node name="NoServers" type="Label" parent="side/margin/options/second"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +text = "c.menu.play.no_servers" +horizontal_alignment = 1 + +[node name="ScrollContainerCustom" type="ScrollContainer" parent="side/margin/options/second"] +layout_mode = 2 +size_flags_vertical = 3 +horizontal_scroll_mode = 0 +script = ExtResource("5_cm120") + +[node name="ServerList" type="VBoxContainer" parent="side/margin/options/second/ScrollContainerCustom"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="spacer" type="Control" parent="side/margin/options/second"] +custom_minimum_size = Vector2(0, 10) +layout_mode = 2 + +[node name="connect" type="HBoxContainer" parent="side/margin/options/second"] +layout_mode = 2 + +[node name="uri" type="LineEdit" parent="side/margin/options/second/connect"] +auto_translate_mode = 2 +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "wss://example.org" + +[node name="connect" type="Button" parent="side/margin/options/second/connect"] +layout_mode = 2 +text = "c.menu.play.connect" + +[node name="server" type="HBoxContainer" parent="side/margin/options/second"] +layout_mode = 2 + +[node name="control" type="Button" parent="side/margin/options/second/server"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "c.menu.play.server" +alignment = 0 + +[node name="connect" type="Button" parent="side/margin/options/second/server"] +layout_mode = 2 +text = "c.menu.play.connect" + +[node name="editor" type="HBoxContainer" parent="side/margin/options/second"] +layout_mode = 2 + +[node name="control" type="Button" parent="side/margin/options/second/editor"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "c.menu.play.editor" +alignment = 0 + +[node name="connect" type="Button" parent="side/margin/options/second/editor"] +layout_mode = 2 +text = "c.menu.play.connect" + +[node name="spacer2" type="Control" parent="side/margin/options/second"] +custom_minimum_size = Vector2(0, 10) +layout_mode = 2 + +[node name="back" type="Button" parent="side/margin/options/second"] +layout_mode = 2 +text = "c.menu.back" +alignment = 0 + +[node name="VBoxContainer" type="VBoxContainer" parent="side/margin/options/second"] +layout_mode = 2 + +[connection signal="text_changed" from="side/margin/options/second/connect/uri" to="." method="_on_uri_text_changed"] +[connection signal="pressed" from="side/margin/options/second/connect/connect" to="." method="_on_connect_pressed"] +[connection signal="pressed" from="side/margin/options/second/server/control" to="." method="_on_server_control_pressed"] +[connection signal="pressed" from="side/margin/options/second/server/connect" to="." method="_on_server_connect_pressed"] +[connection signal="pressed" from="side/margin/options/second/editor/control" to="." method="_on_editor_control_pressed"] +[connection signal="pressed" from="side/margin/options/second/editor/connect" to="." method="_on_editor_connect_pressed"] +[connection signal="pressed" from="side/margin/options/second/back" to="." method="_on_back_pressed"] diff --git a/client/gui/menus/main/server_list_item.gd b/client/gui/menus/main/server_list_item.gd new file mode 100644 index 00000000..0cffdd72 --- /dev/null +++ b/client/gui/menus/main/server_list_item.gd @@ -0,0 +1,38 @@ +# 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/>. +# +class_name ServerListItem +extends PanelContainer + +var error_style_focus: StyleBoxFlat = preload("res://gui/resources/style/error_focus_style.tres") +@onready var title: Label = $MarginContainer/VBoxContainer/Title +@onready var info: Label = $MarginContainer/VBoxContainer/Info +@onready var button: Button = $Button + +func setup(name_: String, online_players: int, version: Array): + title.text = name_ + if version[0] != Multiplayer.VERSION_MAJOR or version[1] > Multiplayer.VERSION_MINOR: + button.disabled = true + button.add_theme_stylebox_override("focus", error_style_focus) + info.text = tr("c.menu.play.server_version_mismatch") + info.add_theme_color_override("font_color", Color("ff2222")) + return + info.text = tr("c.menu.play.server_players").format([online_players]) + + # This node is in group not no_click_sound, so sounds won't be automatically connected + # by menu system. Reason: These nodes are deleted and re-created every few seconds + # in server list, and signals are only connected on ready. + button.pressed.connect(Sound.play_click) + button.mouse_entered.connect(Sound.play_hover) diff --git a/client/gui/menus/main/server_list_item.gd.uid b/client/gui/menus/main/server_list_item.gd.uid new file mode 100644 index 00000000..276bb06f --- /dev/null +++ b/client/gui/menus/main/server_list_item.gd.uid @@ -0,0 +1 @@ +uid://xr5oigbgd0aw diff --git a/client/gui/menus/main/server_list_item.tscn b/client/gui/menus/main/server_list_item.tscn new file mode 100644 index 00000000..40e9eedb --- /dev/null +++ b/client/gui/menus/main/server_list_item.tscn @@ -0,0 +1,39 @@ +[gd_scene load_steps=3 format=3 uid="uid://t2h60dhuvfsk"] + +[ext_resource type="Script" uid="uid://xr5oigbgd0aw" path="res://gui/menus/main/server_list_item.gd" id="1_1n1yg"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1n1yg"] + +[node name="ServerListItem" type="PanelContainer"] +offset_right = 400.0 +offset_bottom = 40.0 +size_flags_horizontal = 3 +theme_override_styles/panel = SubResource("StyleBoxEmpty_1n1yg") +script = ExtResource("1_1n1yg") + +[node name="Button" type="Button" parent="." groups=["no_click_sound"]] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 +mouse_filter = 2 + +[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_colors/font_color = Color(0.87451, 0.87451, 0.87451, 1) +theme_override_font_sizes/font_size = 18 +text = "Example Server" + +[node name="Info" type="Label" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_colors/font_color = Color(0.749781, 0.74978, 0.74978, 1) +theme_override_font_sizes/font_size = 14 +text = "5 players online" |