Push project up

This commit is contained in:
2026-08-23 12:03:58 -05:00
parent 5a3b3a9563
commit e8378cb6fb
34 changed files with 1001 additions and 1 deletions

View File

@@ -1,3 +1,3 @@
# Lobby Cliet # Lobby Cliet
> **Note:** Meant to be exported as a pck and loaded by game-shell [game-shell](https://code.itdominator.com/itdominator/game-shell). > **Note:** Meant to be exported as a pck and loaded by the [game-shell](https://code.itdominator.com/itdominator/game-shell).

43
export_presets.cfg Normal file
View File

@@ -0,0 +1,43 @@
[preset.0]
name="Lobby Client"
platform="Linux"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="resources"
export_files=PackedStringArray("res://scenes/screens/lobby_screen/lobby.gd", "res://scenes/screens/lobby_screen/lobby.tscn", "res://scenes/screens/lobby_screen/lobby_base.gd", "res://scenes/screens/lobby_screen/lobby_client.gd", "res://scenes/screens/lobby_screen/match_entry.gd", "res://scenes/screens/lobby_screen/match_entry.tscn", "res://scenes/ui/lobby/lobby_ui.tscn")
include_filter=""
exclude_filter="globals/*,scripts/*"
export_path="../../builds/desktop/shell-test/modules/lobby-client.x86_64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
shader_baker/enabled=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""

15
globals/globals.gd Normal file
View File

@@ -0,0 +1,15 @@
extends Node
var game_data: GameData
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)

1
globals/globals.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://biu64hvcxb1su

68
globals/message_bus.gd Normal file
View File

@@ -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)

View File

@@ -0,0 +1 @@
uid://dgkbelaqw2a2g

5
icon.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3019 13.7368H12.6973H18.5112C20.0525 13.7368 21.3019 12.5351 21.3019 11.0526C21.3019 9.57018 20.0525 8.36842 18.5112 8.36842C20.0525 8.36842 21.3019 7.16666 21.3019 5.68421C21.3019 4.20176 20.0525 3 18.5112 3H5.48796C3.9467 3 2.69727 4.20176 2.69727 5.68421C2.69727 7.16666 3.9467 8.36842 5.48796 8.36842C3.9467 8.36842 2.69727 9.57018 2.69727 11.0526C2.69727 12.5351 3.9467 13.7368 5.48796 13.7368H11.3019ZM12.9298 5.01316C12.5445 5.01316 12.2321 5.3136 12.2321 5.68421C12.2321 6.05482 12.5445 6.35526 12.9298 6.35526H18.5112C18.8965 6.35526 19.2089 6.05482 19.2089 5.68421C19.2089 5.3136 18.8965 5.01316 18.5112 5.01316H12.9298ZM12.9298 10.3816C12.5445 10.3816 12.2321 10.682 12.2321 11.0526C12.2321 11.4232 12.5445 11.7237 12.9298 11.7237H18.5112C18.8965 11.7237 19.2089 11.4232 19.2089 11.0526C19.2089 10.682 18.8965 10.3816 18.5112 10.3816H12.9298ZM7.34843 5.68421C7.34843 6.17836 6.93195 6.57895 6.4182 6.57895C5.90444 6.57895 5.48796 6.17836 5.48796 5.68421C5.48796 5.19006 5.90444 4.78947 6.4182 4.78947C6.93195 4.78947 7.34843 5.19006 7.34843 5.68421ZM7.34843 11.0526C7.34843 11.5468 6.93195 11.9474 6.4182 11.9474C5.90444 11.9474 5.48796 11.5468 5.48796 11.0526C5.48796 10.5585 5.90444 10.1579 6.4182 10.1579C6.93195 10.1579 7.34843 10.5585 7.34843 11.0526Z" fill="#1C274C"/>
<path opacity="0.6" d="M22 18.211C22 17.8404 21.6876 17.5399 21.3023 17.5399H13.7252C13.5364 17.0914 13.164 16.7332 12.6977 16.5516V13.7373H11.3023V16.5516C10.836 16.7332 10.4636 17.0914 10.2748 17.5399H2.69767C2.31236 17.5399 2 17.8404 2 18.211C2 18.5816 2.31236 18.882 2.69767 18.882H10.2748C10.5508 19.5378 11.2192 20.0005 12 20.0005C12.7808 20.0005 13.4492 19.5378 13.7252 18.882H21.3023C21.6876 18.882 22 18.5816 22 18.211Z" fill="#1C274C"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

43
icon.svg.import Normal file
View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dsiurmg6lea5e"
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

10
lobby_client.tscn Normal file
View File

@@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=3 uid="uid://djc2mihyhpoko"]
[ext_resource type="PackedScene" uid="uid://dy51wny4x53f4" path="res://scripts/data/data_bridge.tscn" id="1_mqgqt"]
[ext_resource type="PackedScene" uid="uid://dkes5cdu45q6e" path="res://scenes/screens/lobby_screen/lobby.tscn" id="2_cirtq"]
[node name="lobby_client" type="Node"]
[node name="data_bridge" parent="." instance=ExtResource("1_mqgqt")]
[node name="lobby" parent="." instance=ExtResource("2_cirtq")]

80
project.godot Normal file
View File

@@ -0,0 +1,80 @@
; 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="Lobby Client"
config/description="A billiards game with many game mode options plus the ability to add more."
run/main_scene="uid://djc2mihyhpoko"
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_pulse={
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}
aim_release={
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}
aim_rotate_left={
"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":65,"key_label":0,"unicode":97,"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":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
aim_rotate_right={
"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":68,"key_label":0,"unicode":100,"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":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
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

View File

@@ -0,0 +1,112 @@
class_name Lobby extends LobbyBase
func _ready() -> void:
setup_signals()
host_address_input.grab_focus()
func _exit_tree() -> void:
# TODO: Maybe no longer needed...
if Globals.multiplayer_data.is_multiplayer_active: return
client._do_wait_close_connection()
func setup_signals() -> void:
MessageBus.subscribe("lobby_wait_for_connection", client._do_wait_for_connection)
MessageBus.subscribe("lobby_close_connection", client._do_wait_close_connection)
MessageBus.subscribe("receive_match_list", _on_receive_match_list)
MessageBus.subscribe("match_list_activate_entry", _on_match_list_entry_activated)
MessageBus.subscribe("match_list_add_entry", _on_match_list_entry_added)
MessageBus.subscribe("match_list_remove_entry", _on_match_list_entry_removed)
MessageBus.subscribe("match_list_entry_load_match", _on_match_list_entry_load_match)
func _server_host_started() -> void:
host_connect_bttn.visible = false
# NOTE: 'matches_list' can be empty; so long as we get the call from the
# server we know we are connected and thus hide respective UI elements.
func _on_receive_match_list(matches_list: Array) -> void:
push_warning("Client Joined Host: Full Match List Recieved...\n", matches_list)
match_create_vbox.visible = true
search_vbox.visible = true
host_disconnect_bttn.visible = true
host_connect_bttn.visible = false
for match_entry in matches_list:
_create_match_entry(match_entry)
client.lobby_fully_connected = true
new_match_name_input.grab_focus()
func _on_match_list_entry_activated(match_id: String) -> void:
for match_entry in match_list.get_children():
match_entry.join_bttn.visible = false
if not match_entry.match_id == match_id: continue
active_match = match_entry
match_entry.join_bttn.text = "Delete"
match_entry.join_bttn.visible = true
match_create_vbox.visible = false
match_search_input.visible = false
match_search_bttn.visible = false
match_entry.join_bttn.pressed.disconnect(_join_match)
match_entry.join_bttn.pressed.connect(
_delete_match.bind(match_entry.match_id)
)
func _on_match_list_entry_added(match_entry: Dictionary) -> void:
push_warning("Client: Added Match List Entry...", match_entry)
_create_match_entry(match_entry)
func _on_match_list_entry_removed(match_id: String) -> void:
push_warning("Client: Removed Match List Entry...", match_id)
if active_match && (match_id == active_match.match_id):
active_match = null
match_create_vbox.visible = true
match_search_input.visible = true
match_search_bttn.visible = false
new_match_name_input.grab_focus()
for match_entry in match_list.get_children():
if not active_match:
match_entry.join_bttn.visible = true
if not match_id == match_entry.match_id: continue
match_entry.queue_free()
func _on_match_list_entry_load_match(match_entry: Dictionary, is_player_1: bool) -> void:
push_warning(
"Client: Loading Game Match...\nMatch Data: ", match_entry, "\nis_player_1: ", is_player_1
)
Globals.multiplayer_data.set_multiplayer_active()
Globals.game_data.set_game_mode(match_entry.type)
Globals.game_data.set_player_id(is_player_1)
Globals.game_state.set_game_scene("res://scenes/game.tscn")
func _create_match_entry(match_entry: Dictionary) -> void:
var container = MATCH_ENTRY.instantiate()
match_list.add_child(container)
container.name_lbl.text = match_entry.name
container.type_lbl.text = match_entry.type
container.match_id = match_entry.match_id
container.join_bttn.pressed.connect(
_join_match.bind(match_entry.match_id)
)
if active_match:
container.join_bttn.visible = false
func _join_match(match_id: String) -> void:
MessageBus.emit_request.rpc_id(1, "match_list_join_entry", match_id)
func _delete_match(match_id: String) -> void:
MessageBus.emit_request.rpc_id(1, "match_list_remove_entry", match_id)

View File

@@ -0,0 +1 @@
uid://dk7afnf7ol7dy

View File

@@ -0,0 +1,42 @@
[gd_scene load_steps=4 format=3 uid="uid://dkes5cdu45q6e"]
[ext_resource type="Script" uid="uid://dk7afnf7ol7dy" path="res://scenes/screens/lobby_screen/lobby.gd" id="1_hhiik"]
[ext_resource type="PackedScene" uid="uid://dg7pgj6i5pk8p" path="res://scenes/ui/lobby/lobby_ui.tscn" id="2_lqt48"]
[ext_resource type="Script" uid="uid://dv7j35h2ngiq7" path="res://scenes/screens/lobby_screen/lobby_client.gd" id="4_glu7g"]
[node name="lobby" type="Node"]
script = ExtResource("1_hhiik")
[node name="lobby_ui" parent="." instance=ExtResource("2_lqt48")]
[node name="host_address_input" parent="lobby_ui/body/left_body/server_host_hbox" index="1"]
context_menu_enabled = false
select_all_on_focus = true
[node name="host_port_range" parent="lobby_ui/body/left_body/server_host_hbox" index="2"]
select_all_on_focus = true
[node name="match_search_input" parent="lobby_ui/body/left_body/search_vbox/search_hbox" index="0"]
context_menu_enabled = false
[node name="right_body" parent="lobby_ui/body" index="1"]
visible = false
[node name="new_match_name_input" parent="lobby_ui/body/right_body/create_match_hbox" index="0"]
context_menu_enabled = false
select_all_on_focus = true
[node name="client" type="Node" parent="."]
script = ExtResource("4_glu7g")
[connection signal="pressed" from="lobby_ui/body/left_body/server_host_hbox/home_bttn" to="." method="_on_home_bttn_pressed"]
[connection signal="pressed" from="lobby_ui/body/left_body/server_host_hbox/host_connect_bttn" to="." method="_on_host_connect_bttn_pressed"]
[connection signal="pressed" from="lobby_ui/body/left_body/server_host_hbox/host_disconnect_bttn" to="." method="_on_host_disconnect_bttn_pressed"]
[connection signal="pressed" from="lobby_ui/body/left_body/search_vbox/search_hbox/match_search_bttn" to="." method="_on_match_search_bttn_pressed"]
[connection signal="pressed" from="lobby_ui/body/right_body/create_match_hbox/match_create_bttn" to="." method="_on_match_create_bttn_pressed"]
[connection signal="pressed" from="lobby_ui/body/right_body/vbox/8ball" to="." method="_on_mode_bttn_pressed" flags=18]
[connection signal="pressed" from="lobby_ui/body/right_body/vbox/9ball" to="." method="_on_mode_bttn_pressed" flags=18]
[connection signal="pressed" from="lobby_ui/body/right_body/vbox/snooker" to="." method="_on_mode_bttn_pressed" flags=18]
[connection signal="pressed" from="lobby_ui/body/right_body/vbox/freeball" to="." method="_on_mode_bttn_pressed" flags=18]
[editable path="lobby_ui"]

View File

@@ -0,0 +1,62 @@
class_name LobbyBase extends Node
const MATCH_ENTRY = preload("res://scenes/screens/lobby_screen/match_entry.tscn")
@onready var host_address_input: LineEdit = $lobby_ui/body/left_body/server_host_hbox/host_address_input
@onready var host_port_range: SpinBox = $lobby_ui/body/left_body/server_host_hbox/host_port_range
@onready var host_connect_bttn: Button = $lobby_ui/body/left_body/server_host_hbox/host_connect_bttn
@onready var host_disconnect_bttn: Button = $lobby_ui/body/left_body/server_host_hbox/host_disconnect_bttn
@onready var search_vbox: VBoxContainer = $lobby_ui/body/left_body/search_vbox
@onready var match_search_input: LineEdit = $lobby_ui/body/left_body/search_vbox/search_hbox/match_search_input
@onready var match_search_bttn: Button = $lobby_ui/body/left_body/search_vbox/search_hbox/match_search_bttn
@onready var match_list: VBoxContainer = $lobby_ui/body/left_body/search_vbox/scroll_container/match_list
@onready var match_create_vbox: VBoxContainer = $lobby_ui/body/right_body
@onready var new_match_name_input: LineEdit = $lobby_ui/body/right_body/create_match_hbox/new_match_name_input
@onready var client: LobbyClient = $client
var active_mode: String = ""
var active_match: HBoxContainer = null
func _on_home_bttn_pressed() -> void:
Globals.game_state.set_game_scene(
"res://scenes/screens/start_screen/start.tscn"
)
func _on_host_connect_bttn_pressed() -> void:
Globals.game_data.game_address = host_address_input.text
Globals.game_data.game_port = int(host_port_range.value)
client.start_client(
Globals.game_data.game_address, Globals.game_data.game_port
)
func _on_host_disconnect_bttn_pressed() -> void:
match_create_vbox.visible = false
search_vbox.visible = false
host_disconnect_bttn.visible = false
host_connect_bttn.visible = true
for match_block in match_list.get_children():
match_block.queue_free()
client.close_connection()
func _on_match_search_bttn_pressed() -> void:
pass
func _on_match_create_bttn_pressed() -> void:
if active_match: return
var match_entry: Dictionary = {
"name": new_match_name_input.text,
"type": active_mode
}
MessageBus.emit_request.rpc("match_list_add_entry", match_entry)
func _on_mode_bttn_pressed(button: Button) -> void:
active_mode = button.name.to_lower()

View File

@@ -0,0 +1 @@
uid://5tvhtoe6fdu1

View File

@@ -0,0 +1,35 @@
class_name LobbyClient extends ClientNetworking
var lobby_fully_connected: bool = false
func _ready() -> void:
pass
func _process(_delta: float) -> void:
pass
func _do_wait_for_connection() -> void:
_wait_for_connection()
while not lobby_fully_connected:
await get_tree().process_frame
func _do_wait_close_connection():
_wait_close_connection()
lobby_fully_connected = false
func client_connected_to_server() -> void:
push_warning("Connected to server!")
func client_disconnected_from_server() -> void:
push_warning("Disconnected from, server...")
func client_connection_failed_to_server() -> void:
push_warning("Connection failed!")
unset_client()

View File

@@ -0,0 +1 @@
uid://dv7j35h2ngiq7

View File

@@ -0,0 +1,8 @@
class_name MatchEntry extends HBoxContainer
@onready var name_lbl: Label = $name_lbl
@onready var type_lbl: Label = $type_lbl
@onready var join_bttn: Button = $join_bttn
var match_id: String = ""

View File

@@ -0,0 +1 @@
uid://ck663xy8rqumo

View File

@@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=3 uid="uid://b5b18vkfe3caa"]
[ext_resource type="Script" uid="uid://ck663xy8rqumo" path="res://scenes/screens/lobby_screen/match_entry.gd" id="1_kw53p"]
[node name="match_entry" type="HBoxContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_kw53p")
[node name="name_lbl" type="Label" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="type_lbl" type="Label" parent="."]
layout_mode = 2
size_flags_horizontal = 3
[node name="join_bttn" type="Button" parent="."]
layout_mode = 2
text = "Join"

View File

@@ -0,0 +1,164 @@
[gd_scene load_steps=3 format=3 uid="uid://dg7pgj6i5pk8p"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e03fk"]
content_margin_left = 4.0
content_margin_top = 4.0
content_margin_right = 4.0
content_margin_bottom = 4.0
bg_color = Color(0.22352941, 0.47058824, 0.23137255, 1)
corner_radius_top_left = 3
corner_radius_top_right = 3
corner_radius_bottom_right = 3
corner_radius_bottom_left = 3
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lqt48"]
content_margin_left = 4.0
content_margin_top = 4.0
content_margin_right = 4.0
content_margin_bottom = 4.0
bg_color = Color(0.84705883, 0.21960784, 0.24705882, 1)
corner_radius_top_left = 3
corner_radius_top_right = 3
corner_radius_bottom_right = 3
corner_radius_bottom_left = 3
[node name="lobby_ui" type="MarginContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 16.0
offset_top = 23.0
offset_right = -19.0
offset_bottom = -27.0
grow_horizontal = 2
grow_vertical = 2
[node name="body" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 3
[node name="left_body" type="VBoxContainer" parent="body"]
layout_mode = 2
size_flags_horizontal = 3
[node name="server_host_hbox" type="HBoxContainer" parent="body/left_body"]
layout_mode = 2
size_flags_horizontal = 3
[node name="home_bttn" type="Button" parent="body/left_body/server_host_hbox"]
layout_mode = 2
text = "Home"
[node name="host_address_input" type="LineEdit" parent="body/left_body/server_host_hbox"]
layout_mode = 2
size_flags_horizontal = 3
text = "127.0.0.1"
placeholder_text = "Server Address: (Eg. 0.0.0.0)"
alignment = 1
max_length = 15
emoji_menu_enabled = false
clear_button_enabled = true
caret_blink = true
[node name="host_port_range" type="SpinBox" parent="body/left_body/server_host_hbox"]
layout_mode = 2
min_value = 1.0
max_value = 65535.0
page = 10.0
value = 8080.0
rounded = true
alignment = 1
[node name="host_connect_bttn" type="Button" parent="body/left_body/server_host_hbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
theme_override_styles/normal = SubResource("StyleBoxFlat_e03fk")
text = "Connect"
[node name="host_disconnect_bttn" type="Button" parent="body/left_body/server_host_hbox"]
visible = false
layout_mode = 2
mouse_default_cursor_shape = 2
theme_override_styles/normal = SubResource("StyleBoxFlat_lqt48")
text = "Disconnect"
[node name="search_vbox" type="VBoxContainer" parent="body/left_body"]
visible = false
layout_mode = 2
size_flags_vertical = 3
[node name="search_hbox" type="HBoxContainer" parent="body/left_body/search_vbox"]
layout_mode = 2
size_flags_horizontal = 3
[node name="match_search_input" type="LineEdit" parent="body/left_body/search_vbox/search_hbox"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Search Match List... "
max_length = 12
emoji_menu_enabled = false
clear_button_enabled = true
caret_blink = true
[node name="match_search_bttn" type="Button" parent="body/left_body/search_vbox/search_hbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
text = "Search"
[node name="scroll_container" type="ScrollContainer" parent="body/left_body/search_vbox"]
layout_mode = 2
size_flags_vertical = 3
[node name="match_list" type="VBoxContainer" parent="body/left_body/search_vbox/scroll_container"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="right_body" type="VBoxContainer" parent="body"]
layout_mode = 2
size_flags_horizontal = 3
[node name="create_match_hbox" type="HBoxContainer" parent="body/right_body"]
layout_mode = 2
size_flags_horizontal = 3
[node name="new_match_name_input" type="LineEdit" parent="body/right_body/create_match_hbox"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "New Match Name..."
max_length = 12
emoji_menu_enabled = false
clear_button_enabled = true
[node name="match_create_bttn" type="Button" parent="body/right_body/create_match_hbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
text = "Create"
[node name="vbox" type="VBoxContainer" parent="body/right_body"]
layout_mode = 2
size_flags_vertical = 3
alignment = 1
[node name="8ball" type="Button" parent="body/right_body/vbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
disabled = true
text = "8-Ball"
[node name="9ball" type="Button" parent="body/right_body/vbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
disabled = true
text = "9-Ball"
[node name="snooker" type="Button" parent="body/right_body/vbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
disabled = true
text = "Snooker"
[node name="freeball" type="Button" parent="body/right_body/vbox"]
layout_mode = 2
mouse_default_cursor_shape = 2
text = "Free Ball"

View File

@@ -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

View File

@@ -0,0 +1 @@
uid://ci57tiuqsx1jp

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://dy51wny4x53f4"]
[ext_resource type="Script" uid="uid://52eithlmedm3" path="res://scripts/data/game_data.gd" id="1_hulqm"]
[ext_resource type="Script" uid="uid://bs4vblwa3u5jq" 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="multiplayer_data" type="Node" parent="."]
script = ExtResource("4_setx2")

34
scripts/data/game_data.gd Normal file
View File

@@ -0,0 +1,34 @@
class_name GameData extends Node
var client1: int
var client2: int
var player_id: String = ""
var game_address: String = "0.0.0.0"
var game_port: int = 8080
var game_mode: String = ""
enum PlayerType {
Player1,
Player2
}
func _init() -> void:
Globals.game_data = self
@rpc("authority", "reliable")
func set_game_address(address: String) -> void:
game_address = address
@rpc("authority", "reliable")
func set_game_port(port: String) -> void:
game_port = int(port)
func set_game_mode(_mode: String) -> void:
pass
func set_player_id(is_player_1: bool) -> void:
player_id = "Player 1" if is_player_1 else "Player 2"

View File

@@ -0,0 +1 @@
uid://52eithlmedm3

View File

@@ -0,0 +1,63 @@
class_name GameState extends Node
@warning_ignore_start("unused_signal")
signal update_cue_cam_position
signal balls_stopped_moving
signal white_ball_sunk
signal white_ball_needs_hard_reset
signal reload_scene
signal process_ball
signal reap_ball
@warning_ignore_restore("unused_signal")
func _init() -> 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_or_null("shell/scene")
if not target:
target = get_tree().root.get_node("game_core/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_or_null("shell/scene")
if not target:
target = get_tree().root.get_node("game_core/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
func switch_active_player() -> void:
# TODO: Move away from using client ID or mask it with a map ID
if Globals.multiplayer_data.current_turn_player_id == Globals.game_data.client1:
Globals.multiplayer_data.rpc(
"set_active_player_id",
Globals.game_data.client2
)
elif Globals.multiplayer_data.current_turn_player_id == Globals.game_data.client2:
Globals.multiplayer_data.rpc(
"set_active_player_id",
Globals.game_data.client1
)

View File

@@ -0,0 +1 @@
uid://rol2c8o8q2ty

View File

@@ -0,0 +1,16 @@
class_name MultiplayerData extends Node
var is_multiplayer_active: bool = false
func _init() -> void:
Globals.multiplayer_data = self
@rpc("authority", "call_local", "reliable")
func set_multiplayer_active() -> void:
is_multiplayer_active = true
@rpc("authority", "call_local", "reliable")
func set_active_player_id(_id: int) -> void:
pass

View File

@@ -0,0 +1 @@
uid://bs4vblwa3u5jq

View File

@@ -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...")

View File

@@ -0,0 +1 @@
uid://bgnr36m8qvbx3

BIN
splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

40
splash.png.import Normal file
View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://7t31fn00rvc1"
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