diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/README.md b/README.md index 6ee3e0d..5d67d07 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # game-shell +> **Note:** Meant to be both a shell and also starting base for games. In shell mode it loads PCK files such as assets, game, loggy-client, and store. In game mode you extend he scripts such as data_bridge and the shell replaces the old with the new. You export as game.pck diff --git a/configs/games.cfg b/configs/games.cfg new file mode 100644 index 0000000..d855d87 --- /dev/null +++ b/configs/games.cfg @@ -0,0 +1,28 @@ +[lobby_load] +; Defaults to joning a lobby server bound to 8080. +; Has clients go through lobby to load a mode. +client1="client host_freeball freeball88" +client2="client join freeball88" + +[only_game_server] +server="server_5010 game freeball" + +[8ball_game_server] +server="server_5001 game 8ball" +client1="join_server 127.0.0.1 5001" +client2="join_server 127.0.0.1 5001" + +[9ball_game_server] +server="server_5002 game 9ball" +client1="join_server 127.0.0.1 5002" +client2="join_server 127.0.0.1 5002" + +[snooker_game_server] +server="server_5003 game snooker" +client1="join_server 127.0.0.1 5003" +client2="join_server 127.0.0.1 5003" + +[freeball_game_server] +server="server_5004 game freeball" +client1="join_server 127.0.0.1 5004" +client2="join_server 127.0.0.1 5004" diff --git a/globals/globals.gd b/globals/globals.gd new file mode 100644 index 0000000..e9db016 --- /dev/null +++ b/globals/globals.gd @@ -0,0 +1,17 @@ +extends Node + +# NOTE: These should get overriden by '.pck' packs that load their own versions. +var game_data: GameData +var game_state: GameState +var lobby_data: LobbyData +var multiplayer_data: MultiplayerData + + +func cache_invalidate_load_resource(target: String) -> Resource: + # NOTE: Deep replace version b/c we don't want to use an autoloads + # that does this replasce before any nodes actually load. + ResourceLoader.load(target, "", ResourceLoader.CACHE_MODE_REPLACE_DEEP) + + # NOTE: Let prior call propigate naturally. (Unsure when...) + # Enforce new script/node from pck called here. + return ResourceLoader.load(target, "", ResourceLoader.CACHE_MODE_IGNORE_DEEP) diff --git a/globals/globals.gd.uid b/globals/globals.gd.uid new file mode 100644 index 0000000..5d3f638 --- /dev/null +++ b/globals/globals.gd.uid @@ -0,0 +1 @@ +uid://biu64hvcxb1su diff --git a/globals/message_bus.gd b/globals/message_bus.gd new file mode 100644 index 0000000..6a6eac9 --- /dev/null +++ b/globals/message_bus.gd @@ -0,0 +1,68 @@ +extends Node + + +var message_types: Dictionary[String, Array] = {} + + +func subscribe(id: String, callback: Callable) -> void: + if not message_types.has(id): + message_types.set(id, Array()) + + message_types.get(id).append(callback) + + +func clear_voided_listeners() -> void: + for mtype in message_types.keys(): + var mlisteners: Array = message_types.get(mtype) + for mlistener in mlisteners: + if mlistener.is_valid(): continue + mlisteners.erase(mlistener) + + +func emit_local(id: String, data: Variant, expand: bool = false) -> void: + emit_propagation(id, data, expand) + + +# TODO: Need to actually validate client request. Also, message bus is more +# about server talking to clients than clients to server. I.E, reducing +# the number of needed @rpc method decorator bindings. +@rpc("any_peer", "call_remote", "reliable") +func emit_request(id: String, data: Variant, expand: bool = false) -> void: + if not multiplayer.is_server(): return + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) + return + + emit_propagation(id, data, expand) + +@rpc("authority", "call_local", "reliable") +func emit_propagation(id: String, data: Variant, expand: bool = false) -> void: + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) + return + + for callback: Callable in message_types.get(id): + if data == null: + callback.call() + continue + + if not expand: + callback.call(data) + else: + callback.callv(data) + +@rpc("authority", "call_remote", "reliable") +func emit_propagation_clients_only(id: String, data: Variant, expand: bool = false) -> void: + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) + return + + for callback: Callable in message_types.get(id): + if data == null: + callback.call() + continue + + if not expand: + callback.call(data) + else: + callback.callv(data) diff --git a/globals/message_bus.gd.uid b/globals/message_bus.gd.uid new file mode 100644 index 0000000..8c3abe4 --- /dev/null +++ b/globals/message_bus.gd.uid @@ -0,0 +1 @@ +uid://dgkbelaqw2a2g diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..eb6ee6e --- /dev/null +++ b/icon.svg @@ -0,0 +1,654 @@ + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..bf98421 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b5u0mk2y43ht2" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/import_manager.gd b/import_manager.gd new file mode 100644 index 0000000..85c6a02 --- /dev/null +++ b/import_manager.gd @@ -0,0 +1,15 @@ +@tool class_name ImportManager extends EditorScenePostImport + + +# NOTE: Example of editing an import +#func _post_import(scene: Node) -> Object: +# if scene.name == "balls": +# scene.name = "bodies" +# setup_balls_scene(scene) + +# return scene # NOTE: Must return the scene no matter what + +#func setup_balls_scene(scene: Node) -> void: +# for node in scene.get_children(): +# # NOTE: Would do further logic here +# setup_balls_scene(node) diff --git a/import_manager.gd.uid b/import_manager.gd.uid new file mode 100644 index 0000000..b9a5959 --- /dev/null +++ b/import_manager.gd.uid @@ -0,0 +1 @@ +uid://jfenmjssu7v7 diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..2f0b35a --- /dev/null +++ b/project.godot @@ -0,0 +1,56 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Game Shell" +config/description="A shell setup to load core game related modules such as a multiplayer lobby client or the core game files." +run/main_scene="uid://04nv87epssf4" +run/print_header=false +config/features=PackedStringArray("4.5", "Forward Plus") +run/max_fps=30 +boot_splash/bg_color=Color(0, 0, 0, 1) +boot_splash/image="uid://cwqth1sgffu3c" +config/icon="res://icon.svg" +boot_splash/minimum_display_time=2500 + +[autoload] + +Globals="*res://globals/globals.gd" +MessageBus="*res://globals/message_bus.gd" + +[editor] + +movie_writer/fps=30 +naming/node_name_casing=2 +naming/script_name_casing=2 + +[input] + +aim_incline={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +aim_decline={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} + +[physics] + +3d/physics_engine="Jolt Physics" +jolt_physics_3d/simulation/velocity_steps=20 +jolt_physics_3d/simulation/position_steps=20 +3d/simulation/position_steps=10 +3d/simulation/velocity_steps=10 diff --git a/scenes/environments/base_environment.gd b/scenes/environments/base_environment.gd new file mode 100644 index 0000000..e9483da --- /dev/null +++ b/scenes/environments/base_environment.gd @@ -0,0 +1,5 @@ +class_name BaseEnvironment extends Node3D + + +func _ready() -> void: + pass diff --git a/scenes/environments/base_environment.gd.uid b/scenes/environments/base_environment.gd.uid new file mode 100644 index 0000000..f8dad62 --- /dev/null +++ b/scenes/environments/base_environment.gd.uid @@ -0,0 +1 @@ +uid://cvsrejn43b7xu diff --git a/scenes/environments/base_environment.tscn b/scenes/environments/base_environment.tscn new file mode 100644 index 0000000..6ceab5d --- /dev/null +++ b/scenes/environments/base_environment.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=5 format=3 uid="uid://djtq6hbp70kut"] + +[ext_resource type="Script" uid="uid://cvsrejn43b7xu" path="res://scenes/environments/base_environment.gd" id="1_pm2xn"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_yw8f4"] + +[sub_resource type="Sky" id="Sky_uwrxv"] +sky_material = SubResource("ProceduralSkyMaterial_yw8f4") + +[sub_resource type="Environment" id="Environment_jtak5"] +background_mode = 2 +sky = SubResource("Sky_uwrxv") +ambient_light_source = 3 +reflected_light_source = 2 + +[node name="base_environment" type="Node3D"] +script = ExtResource("1_pm2xn") + +[node name="world" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_jtak5") + +[node name="sun" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.49999997, 0.43301272, -0.75000006, 0, 0.8660254, 0.50000006, 0.86602545, -0.24999999, 0.43301266, 0, 225, 0) + +[node name="sounds" type="Node3D" parent="."] diff --git a/scenes/screens/start_screen/start.gd b/scenes/screens/start_screen/start.gd new file mode 100644 index 0000000..1ae5c3c --- /dev/null +++ b/scenes/screens/start_screen/start.gd @@ -0,0 +1,9 @@ +class_name StartMenu extends Node3D + + +@onready var base_environment: Node = $base_environment +@onready var animation_player: AnimationPlayer = $animation_player + + +func _ready() -> void: + animation_player.play("rotation") diff --git a/scenes/screens/start_screen/start.gd.uid b/scenes/screens/start_screen/start.gd.uid new file mode 100644 index 0000000..8672b29 --- /dev/null +++ b/scenes/screens/start_screen/start.gd.uid @@ -0,0 +1 @@ +uid://cywa27h25s1j8 diff --git a/scenes/screens/start_screen/start.tscn b/scenes/screens/start_screen/start.tscn new file mode 100644 index 0000000..a5aec89 --- /dev/null +++ b/scenes/screens/start_screen/start.tscn @@ -0,0 +1,61 @@ +[gd_scene load_steps=7 format=3 uid="uid://1uhmlnh88yq7"] + +[ext_resource type="Script" uid="uid://cywa27h25s1j8" path="res://scenes/screens/start_screen/start.gd" id="1_mqdda"] +[ext_resource type="PackedScene" uid="uid://djtq6hbp70kut" path="res://scenes/environments/base_environment.tscn" id="2_7nvb2"] +[ext_resource type="PackedScene" uid="uid://da0ok71rkjpx8" path="res://scenes/ui/start_screen/start_ui.tscn" id="4_hk434"] + +[sub_resource type="Animation" id="Animation_qell1"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("rotation_dolly:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_rxs04"] +resource_name = "rotation" +length = 60.0 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("rotation_dolly:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 60), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, 6.2831855, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_cn28k"] +_data = { +&"RESET": SubResource("Animation_qell1"), +&"rotation": SubResource("Animation_rxs04") +} + +[node name="start_screen" type="Node3D"] +script = ExtResource("1_mqdda") + +[node name="base_environment" parent="." instance=ExtResource("2_7nvb2")] + +[node name="rotation_dolly" type="Node3D" parent="."] + +[node name="camera" type="Camera3D" parent="rotation_dolly"] +transform = Transform3D(0.9995127, 0.012299462, -0.028690739, 0, 0.9191053, 0.39401212, 0.031215947, -0.39382014, 0.9186573, 0.020791333, 1.2903607, 1.9422052) +current = true + +[node name="start_ui" parent="rotation_dolly/camera" instance=ExtResource("4_hk434")] + +[node name="animation_player" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_cn28k") +} diff --git a/scenes/ui/start_screen/start_ui.gd b/scenes/ui/start_screen/start_ui.gd new file mode 100644 index 0000000..0094d89 --- /dev/null +++ b/scenes/ui/start_screen/start_ui.gd @@ -0,0 +1 @@ +class_name StartMenuControls extends Control diff --git a/scenes/ui/start_screen/start_ui.gd.uid b/scenes/ui/start_screen/start_ui.gd.uid new file mode 100644 index 0000000..804d190 --- /dev/null +++ b/scenes/ui/start_screen/start_ui.gd.uid @@ -0,0 +1 @@ +uid://ykbcl0j1wouh diff --git a/scenes/ui/start_screen/start_ui.tscn b/scenes/ui/start_screen/start_ui.tscn new file mode 100644 index 0000000..fd6e85c --- /dev/null +++ b/scenes/ui/start_screen/start_ui.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=3 format=3 uid="uid://da0ok71rkjpx8"] + +[ext_resource type="Script" uid="uid://ykbcl0j1wouh" path="res://scenes/ui/start_screen/start_ui.gd" id="1_mwcbl"] + +[sub_resource type="LabelSettings" id="LabelSettings_o8har"] +font_size = 45 +font_color = Color(1, 0.10980392, 0.02745098, 1) +outline_size = 5 + +[node name="start_ui" 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_mwcbl") + +[node name="vbox" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +alignment = 1 + +[node name="alert" type="Label" parent="vbox"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 6 +text = "No Game PCK Loaded" +label_settings = SubResource("LabelSettings_o8har") +uppercase = true diff --git a/scripts/client_networking.gd b/scripts/client_networking.gd new file mode 100644 index 0000000..9078f70 --- /dev/null +++ b/scripts/client_networking.gd @@ -0,0 +1,67 @@ +class_name ClientNetworking extends Node + + +var peer: ENetMultiplayerPeer + + +func start_client(address: String = "127.0.0.1", port: int = 8080) -> void: + if peer: return + + push_warning("Client Starting... Address: ", address, " Port: ", port) + # TODO: Add throbber or other indication of connection attempt. + + peer = ENetMultiplayerPeer.new() + peer.create_client(address, port) + + multiplayer.multiplayer_peer = peer + multiplayer.connected_to_server.connect(client_connected_to_server) + multiplayer.server_disconnected.connect(client_disconnected_from_server) + multiplayer.connection_failed.connect(client_connection_failed_to_server) + + +func _wait_for_connection() -> void: + while not peer: + await get_tree().process_frame + + while peer.get_connection_status() != 2: + await get_tree().process_frame + +func _wait_close_connection(): + close_connection() + + while peer: + await get_tree().process_frame + + +func client_connected_to_server() -> void: + assert(false, "This method needs to be overridden...") + +func client_disconnected_from_server() -> void: + assert(false, "This method needs to be overridden...") + + +func client_connection_failed_to_server() -> void: + assert(false, "This method needs to be overridden...") + + +func close_connection() -> void: + if not peer: return + + push_warning("Disconnected from, server...") + + unset_client() + + +func unset_client() -> void: + if not peer: return + if not multiplayer: + peer.close() + peer = null + return + + multiplayer.connected_to_server.disconnect(client_connected_to_server) + multiplayer.connection_failed.disconnect(client_connection_failed_to_server) + multiplayer.server_disconnected.disconnect(client_disconnected_from_server) + + peer.close() + peer = null diff --git a/scripts/client_networking.gd.uid b/scripts/client_networking.gd.uid new file mode 100644 index 0000000..be0bb54 --- /dev/null +++ b/scripts/client_networking.gd.uid @@ -0,0 +1 @@ +uid://ci57tiuqsx1jp diff --git a/scripts/controllers/networking/game_client.gd b/scripts/controllers/networking/game_client.gd new file mode 100644 index 0000000..30198b8 --- /dev/null +++ b/scripts/controllers/networking/game_client.gd @@ -0,0 +1,42 @@ +class_name GameClient extends ClientNetworking + + +func _ready() -> void: + setup_signals() + + +func setup_signals() -> void: + MessageBus.subscribe("game_start_client", _start_client) + + MessageBus.subscribe("game_wait_for_connection", _wait_for_connection) + MessageBus.subscribe("game_close_connection", _wait_close_connection) + MessageBus.subscribe("game_peer_disconnected", _on_game_peer_disconnected) + +func _start_client(address: String = "127.0.0.1", port: int = 8080) -> void: + if peer: return + start_client(address, port) + +func _on_game_peer_disconnected() -> void: + close_connection() + + Globals.multiplayer_data.reset() + Globals.lobby_data.go_back_to_match_screen() + MessageBus.clear_voided_listeners() + +func client_connected_to_server() -> void: + push_warning("Connected to server!") + +func close_connection() -> void: + if not peer: return + + push_warning("Disconnected from, server...") + + unset_client() + +func client_disconnected_from_server() -> void: + push_warning("Disconnected from, server...") + +func client_connection_failed_to_server() -> void: + push_warning("Connection failed!") + + unset_client() diff --git a/scripts/controllers/networking/game_client.gd.uid b/scripts/controllers/networking/game_client.gd.uid new file mode 100644 index 0000000..b8987a2 --- /dev/null +++ b/scripts/controllers/networking/game_client.gd.uid @@ -0,0 +1 @@ +uid://cjtu1d1j35r32 diff --git a/scripts/controllers/networking/game_client.tscn b/scripts/controllers/networking/game_client.tscn new file mode 100644 index 0000000..1d4e2ae --- /dev/null +++ b/scripts/controllers/networking/game_client.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://cbvv2msu13vr2"] + +[ext_resource type="Script" uid="uid://cjtu1d1j35r32" path="res://scripts/controllers/networking/game_client.gd" id="1_tea1p"] + +[node name="client_net" type="Node"] +script = ExtResource("1_tea1p") diff --git a/scripts/controllers/networking/game_server.gd b/scripts/controllers/networking/game_server.gd new file mode 100644 index 0000000..44eb100 --- /dev/null +++ b/scripts/controllers/networking/game_server.gd @@ -0,0 +1,31 @@ +class_name GameServer extends ServerNetworking + + +func _ready() -> void: + setup_signals() + + +func setup_signals() -> void: + pass + +func server_client_connected(id: int) -> void: + push_warning("Client Connected... ID: ", id) + + if not Globals.game_data.client1: + Globals.game_data.client1 = id + elif not Globals.game_data.client2: + Globals.game_data.client2 = id + + if Globals.game_data.client1 and Globals.game_data.client2: + Globals.multiplayer_data.init_match() + + # TODO: Add watch match feature... + +func server_client_disconnected(id: int) -> void: + push_warning("Client Disconnected... ID: ", id) + + MessageBus.emit_propagation_clients_only.rpc("game_peer_disconnected", null) + + await get_tree().create_timer(5.0).timeout + # NOTE: Quits game server instance. + get_tree().quit() diff --git a/scripts/controllers/networking/game_server.gd.uid b/scripts/controllers/networking/game_server.gd.uid new file mode 100644 index 0000000..8a59b5a --- /dev/null +++ b/scripts/controllers/networking/game_server.gd.uid @@ -0,0 +1 @@ +uid://bndylf4rwtlkn diff --git a/scripts/controllers/networking/game_server.tscn b/scripts/controllers/networking/game_server.tscn new file mode 100644 index 0000000..29115c7 --- /dev/null +++ b/scripts/controllers/networking/game_server.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bss61m8hfvab3"] + +[ext_resource type="Script" uid="uid://bndylf4rwtlkn" path="res://scripts/controllers/networking/game_server.gd" id="1_3xapr"] + +[node name="server_net" type="Node"] +script = ExtResource("1_3xapr") diff --git a/scripts/data/data_bridge.tscn b/scripts/data/data_bridge.tscn new file mode 100644 index 0000000..fc96354 --- /dev/null +++ b/scripts/data/data_bridge.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=5 format=3 uid="uid://dy51wny4x53f4"] + +[ext_resource type="Script" uid="uid://b808va021l1w7" path="res://scripts/data/game_data.gd" id="1_hulqm"] +[ext_resource type="Script" uid="uid://cai8lpy7e00d6" path="res://scripts/data/game_state.gd" id="2_6ash1"] +[ext_resource type="Script" uid="uid://cihlohg5ouy6q" path="res://scripts/data/lobby_data.gd" id="3_80q4n"] +[ext_resource type="Script" uid="uid://dof720ujunrw8" path="res://scripts/data/multiplayer_data.gd" id="4_setx2"] + +[node name="data_bridge" type="Node"] + +[node name="game_data" type="Node" parent="."] +script = ExtResource("1_hulqm") + +[node name="game_state" type="Node" parent="."] +script = ExtResource("2_6ash1") + +[node name="lobby_data" type="Node" parent="."] +script = ExtResource("3_80q4n") + +[node name="multiplayer_data" type="Node" parent="."] +script = ExtResource("4_setx2") diff --git a/scripts/data/game_data.gd b/scripts/data/game_data.gd new file mode 100644 index 0000000..267c272 --- /dev/null +++ b/scripts/data/game_data.gd @@ -0,0 +1,5 @@ +class_name GameData extends Node + + +func _ready() -> void: + Globals.game_data = self diff --git a/scripts/data/game_data.gd.uid b/scripts/data/game_data.gd.uid new file mode 100644 index 0000000..2186e24 --- /dev/null +++ b/scripts/data/game_data.gd.uid @@ -0,0 +1 @@ +uid://b808va021l1w7 diff --git a/scripts/data/game_state.gd b/scripts/data/game_state.gd new file mode 100644 index 0000000..d50b03f --- /dev/null +++ b/scripts/data/game_state.gd @@ -0,0 +1,32 @@ +class_name GameState extends Node + + +func _ready() -> void: + Globals.game_state = self + +func load_game_scene(scene_str: String) -> void: + var scene = load(scene_str).instantiate() + var target = get_tree().root.get_node("shell/scene") + + target.add_child(scene) + +func set_game_scene(scene_str: String) -> void: + var scene = load(scene_str).instantiate() + var target = get_tree().root.get_node("shell/scene") + + if "game" in scene_str: + scene.name = "game" + elif "lobby" in scene_str: + scene.name = "lobby_screen" + elif "start" in scene_str: + scene.name = "start_screen" + + clear_game_scene(target) + + target.add_child(scene) + +func clear_game_scene(container: Node) -> void: + for child in container.get_children(): + child.queue_free() + + await get_tree().process_frame diff --git a/scripts/data/game_state.gd.uid b/scripts/data/game_state.gd.uid new file mode 100644 index 0000000..0e72b41 --- /dev/null +++ b/scripts/data/game_state.gd.uid @@ -0,0 +1 @@ +uid://cai8lpy7e00d6 diff --git a/scripts/data/lobby_data.gd b/scripts/data/lobby_data.gd new file mode 100644 index 0000000..db20fd5 --- /dev/null +++ b/scripts/data/lobby_data.gd @@ -0,0 +1,5 @@ +class_name LobbyData extends Node + + +func _init() -> void: + Globals.lobby_data = self diff --git a/scripts/data/lobby_data.gd.uid b/scripts/data/lobby_data.gd.uid new file mode 100644 index 0000000..32b680b --- /dev/null +++ b/scripts/data/lobby_data.gd.uid @@ -0,0 +1 @@ +uid://cihlohg5ouy6q diff --git a/scripts/data/multiplayer_data.gd b/scripts/data/multiplayer_data.gd new file mode 100644 index 0000000..0305163 --- /dev/null +++ b/scripts/data/multiplayer_data.gd @@ -0,0 +1,13 @@ +class_name MultiplayerData extends Node + + +var is_multiplayer_active: bool = false +var multiplayer_synchronizer: MultiplayerSynchronizer = MultiplayerSynchronizer.new() +var synchronizer_config: SceneReplicationConfig = SceneReplicationConfig.new() + + +func _ready() -> void: + Globals.multiplayer_data = self + multiplayer_synchronizer.name = "multiplayer_synchronizer" + multiplayer_synchronizer.replication_config = synchronizer_config + multiplayer_synchronizer.root_path = "/root/shell" diff --git a/scripts/data/multiplayer_data.gd.uid b/scripts/data/multiplayer_data.gd.uid new file mode 100644 index 0000000..998ae72 --- /dev/null +++ b/scripts/data/multiplayer_data.gd.uid @@ -0,0 +1 @@ +uid://dof720ujunrw8 diff --git a/scripts/server_networking.gd b/scripts/server_networking.gd new file mode 100644 index 0000000..df23922 --- /dev/null +++ b/scripts/server_networking.gd @@ -0,0 +1,47 @@ +class_name ServerNetworking extends Node + + +var peer: ENetMultiplayerPeer + + +func _ready() -> void: + pass + + +func start_server(address: String = "0.0.0.0", port: int = 8080) -> void: + if peer: return + + push_warning("Server Starting... Address: ", address, " Port: ", port) + + peer = ENetMultiplayerPeer.new() + peer.set_bind_ip(address) + + var state = peer.create_server(port) + match state: + OK: + push_warning("Server Started: ", state) + + multiplayer.multiplayer_peer = peer + multiplayer.peer_connected.connect(server_client_connected) + multiplayer.peer_disconnected.connect(server_client_disconnected) + ERR_ALREADY_IN_USE: + peer.close() + peer = null + start_server(address, port) + ERR_CANT_CREATE: + push_warning("Couldn't create server...") + +func close_connection() -> void: + push_warning("Server Closed...") + + multiplayer.peer_connected.disconnect(server_client_connected) + multiplayer.peer_disconnected.disconnect(server_client_disconnected) + + peer.close() + peer = null + +func server_client_connected(_id: int) -> void: + assert(false, "This method needs to be overridden...") + +func server_client_disconnected(_id: int) -> void: + assert(false, "This method needs to be overridden...") diff --git a/scripts/server_networking.gd.uid b/scripts/server_networking.gd.uid new file mode 100644 index 0000000..c819b58 --- /dev/null +++ b/scripts/server_networking.gd.uid @@ -0,0 +1 @@ +uid://bgnr36m8qvbx3 diff --git a/shell.gd b/shell.gd new file mode 100644 index 0000000..a5dcebc --- /dev/null +++ b/shell.gd @@ -0,0 +1,62 @@ +class_name Shell extends Node + + +@onready var game_server: GameServer = $game_server +@onready var game_client: GameClient = $game_client + + +func _ready() -> void: + _load_resources() + _load_scene() + #_parse_args() + + +func _load_resources(): + _load_asset_pck() + _load_game_pck() + _load_lobby_pck() + _load_store_pck() + + +func _load_asset_pck(): + _load_resource_pck("assets.pck") + +func _load_game_pck(): + _load_resource_pck("game.pck") + + $data_bridge.free() + var data_bridge = Globals.cache_invalidate_load_resource( + "res://scripts/data/data_bridge.tscn" + ).instantiate() + + add_child(data_bridge) + move_child(data_bridge, 0) + +func _load_lobby_pck(): + _load_resource_pck("lobby-client.pck") + +func _load_store_pck(): + _load_resource_pck("store.pck") + +func _load_resource_pck(target: String): + #var TARGET_PCK := OS.get_executable_path().get_base_dir() + "/modules/" + target + var TARGET_PCK = "/home/abaddon/Coding/Projects/Active/Godot_Projects/builds/desktop/shell-test/modules/" + target + push_warning("PCK Path: ", TARGET_PCK) + + if not FileAccess.file_exists(TARGET_PCK): + push_warning(target + " PCK is missing.") + return + + var target_pck_loaded := ProjectSettings.load_resource_pack(TARGET_PCK, true) + if not target_pck_loaded: + push_error("Failed to load " + target + " PCK.") + return + + +func _load_scene(): + add_child(Globals.multiplayer_data.multiplayer_synchronizer) + move_child(Globals.multiplayer_data.multiplayer_synchronizer, 0) + + Globals.game_state.set_game_scene( + "res://scenes/screens/start_screen/start.tscn" + ) diff --git a/shell.gd.uid b/shell.gd.uid new file mode 100644 index 0000000..e86cca3 --- /dev/null +++ b/shell.gd.uid @@ -0,0 +1 @@ +uid://dbca7qndk7coq diff --git a/shell.tscn b/shell.tscn new file mode 100644 index 0000000..c95d073 --- /dev/null +++ b/shell.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=5 format=3 uid="uid://04nv87epssf4"] + +[ext_resource type="Script" uid="uid://dbca7qndk7coq" path="res://shell.gd" id="1_bhs8v"] +[ext_resource type="PackedScene" uid="uid://dy51wny4x53f4" path="res://scripts/data/data_bridge.tscn" id="1_xa5nf"] +[ext_resource type="PackedScene" uid="uid://cbvv2msu13vr2" path="res://scripts/controllers/networking/game_client.tscn" id="3_hkpkv"] +[ext_resource type="PackedScene" uid="uid://bss61m8hfvab3" path="res://scripts/controllers/networking/game_server.tscn" id="4_cni66"] + +[node name="shell" type="Node"] +script = ExtResource("1_bhs8v") + +[node name="data_bridge" parent="." instance=ExtResource("1_xa5nf")] + +[node name="game_client" parent="." instance=ExtResource("3_hkpkv")] + +[node name="game_server" parent="." instance=ExtResource("4_cni66")] + +[node name="scene" type="Node" parent="."] diff --git a/splash.png b/splash.png new file mode 100644 index 0000000..e9dd451 Binary files /dev/null and b/splash.png differ diff --git a/splash.png.import b/splash.png.import new file mode 100644 index 0000000..46a8e03 --- /dev/null +++ b/splash.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwqth1sgffu3c" +path="res://.godot/imported/splash.png-929ed8a00b89ba36c51789452f874c77.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://splash.png" +dest_files=["res://.godot/imported/splash.png-929ed8a00b89ba36c51789452f874c77.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1