Initial push
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
@@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
@@ -0,0 +1,3 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
||||
@@ -0,0 +1,2 @@
|
||||
class_name ClientInterface
|
||||
extends Control
|
||||
@@ -0,0 +1 @@
|
||||
uid://c0cqkatyo4uj1
|
||||
@@ -0,0 +1,41 @@
|
||||
[preset.0]
|
||||
|
||||
name="Linux"
|
||||
platform="Linux"
|
||||
runnable=true
|
||||
advanced_options=false
|
||||
dedicated_server=false
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path="../00 Exports/magician/magician_server.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
|
||||
binary_format/architecture="x86_64"
|
||||
ssh_remote_deploy/enabled=false
|
||||
ssh_remote_deploy/host="fish"
|
||||
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}\""
|
||||
@@ -0,0 +1,79 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://gqrdpjslr4np"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bfaxxdr7v0emr" path="res://web_client.gd" id="1_80nbo"]
|
||||
[ext_resource type="Script" uid="uid://c0cqkatyo4uj1" path="res://client_interface.gd" id="2_e2o6t"]
|
||||
|
||||
[sub_resource type="SystemFont" id="SystemFont_80nbo"]
|
||||
font_names = PackedStringArray("IBM Plex Mono")
|
||||
font_weight = 500
|
||||
|
||||
[node name="Game" type="Node"]
|
||||
|
||||
[node name="WebClient" type="Node" parent="." node_paths=PackedStringArray("name_input", "session_code_input", "output", "create_lobby_button", "join_lobby_button", "disconnect_lobby_button")]
|
||||
script = ExtResource("1_80nbo")
|
||||
name_input = NodePath("../ClientInterface/HBoxContainer/VBoxContainer/NameInput")
|
||||
session_code_input = NodePath("../ClientInterface/HBoxContainer/VBoxContainer/SessionCodeInput")
|
||||
output = NodePath("../ClientInterface/HBoxContainer/Output")
|
||||
create_lobby_button = NodePath("../ClientInterface/HBoxContainer/VBoxContainer/CreateLobbyButton")
|
||||
join_lobby_button = NodePath("../ClientInterface/HBoxContainer/VBoxContainer/JoinLobbyButton")
|
||||
disconnect_lobby_button = NodePath("../ClientInterface/HBoxContainer/VBoxContainer/DisconnectLobbyButton")
|
||||
|
||||
[node name="ClientInterface" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("2_e2o6t")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="ClientInterface"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
color = Color(0.34, 0.33116, 0.2992, 1)
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="ClientInterface"]
|
||||
layout_mode = 0
|
||||
offset_right = 800.0
|
||||
offset_bottom = 1080.0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(300, 0)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="NameInput" type="LineEdit" parent="ClientInterface/HBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
placeholder_text = "Your Name"
|
||||
|
||||
[node name="CreateLobbyButton" type="Button" parent="ClientInterface/HBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Create Lobby"
|
||||
|
||||
[node name="SessionCodeInput" type="LineEdit" parent="ClientInterface/HBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
placeholder_text = "Lobby Code"
|
||||
|
||||
[node name="JoinLobbyButton" type="Button" parent="ClientInterface/HBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Join Lobby"
|
||||
|
||||
[node name="DisconnectLobbyButton" type="Button" parent="ClientInterface/HBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
disabled = true
|
||||
text = "Disconnect"
|
||||
|
||||
[node name="Output" type="Label" parent="ClientInterface/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(64, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 1
|
||||
theme_override_fonts/font = SubResource("SystemFont_80nbo")
|
||||
autowrap_mode = 2
|
||||
|
||||
[connection signal="pressed" from="ClientInterface/HBoxContainer/VBoxContainer/CreateLobbyButton" to="WebClient" method="_on_create_lobby_button_pressed"]
|
||||
[connection signal="pressed" from="ClientInterface/HBoxContainer/VBoxContainer/JoinLobbyButton" to="WebClient" method="_on_join_lobby_button_pressed"]
|
||||
[connection signal="pressed" from="ClientInterface/HBoxContainer/VBoxContainer/DisconnectLobbyButton" to="WebClient" method="_on_disconnect_lobby_button_pressed"]
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
||||
|
After Width: | Height: | Size: 994 B |
@@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dtu0pfws0gha4"
|
||||
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/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
@@ -0,0 +1,30 @@
|
||||
; 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="magician"
|
||||
run/main_scene="uid://gqrdpjslr4np"
|
||||
config/features=PackedStringArray("4.4", "GL Compatibility")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
RPCHandler="*res://rpc_handler.tscn"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1920
|
||||
window/size/viewport_height=1080
|
||||
|
||||
[rendering]
|
||||
|
||||
renderer/rendering_method="gl_compatibility"
|
||||
renderer/rendering_method.mobile="gl_compatibility"
|
||||
@@ -0,0 +1,14 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dd3obeotog37w"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_flq8k"]
|
||||
script/source = "extends Node
|
||||
|
||||
@rpc(\"any_peer\", \"call_local\", \"reliable\")
|
||||
func ring_bell(id: int) -> void:
|
||||
$BellLabel.text = str(id) + \" has rung the bell!\"
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
$BellLabel.text = \"\"
|
||||
"
|
||||
|
||||
[node name="RPCHandler" type="Node"]
|
||||
script = SubResource("GDScript_flq8k")
|
||||
@@ -0,0 +1,60 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cgffw8lmsypov"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bfaxxdr7v0emr" path="res://web_client.gd" id="1_eergy"]
|
||||
|
||||
[node name="Client" type="Control" node_paths=PackedStringArray("name_input", "session_code_input")]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_eergy")
|
||||
name_input = NodePath("VBoxContainer/NameInput")
|
||||
session_code_input = NodePath("VBoxContainer/SessionCodeInput")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 466.0
|
||||
offset_top = 312.0
|
||||
offset_right = 609.0
|
||||
offset_bottom = 335.0
|
||||
text = "I WILL CLIENT YOU"
|
||||
|
||||
[node name="BellLabel" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 620.0
|
||||
offset_top = 658.0
|
||||
offset_right = 1285.0
|
||||
offset_bottom = 736.0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -250.0
|
||||
offset_top = -80.0
|
||||
offset_right = 250.0
|
||||
offset_bottom = 80.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="NameInput" type="LineEdit" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="CreateSessionButton" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Create"
|
||||
|
||||
[node name="SessionCodeInput" type="LineEdit" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ConnectButton" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Connect"
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/CreateSessionButton" to="." method="_on_create_session_button_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/ConnectButton" to="." method="_on_connect_button_pressed"]
|
||||
@@ -0,0 +1,25 @@
|
||||
class_name Server
|
||||
extends Control
|
||||
|
||||
var _peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||
var _port: int = 9974
|
||||
|
||||
@export var text_output: Label
|
||||
|
||||
func _ready() -> void:
|
||||
multiplayer.peer_connected.connect(_on_peer_connected)
|
||||
|
||||
_write_line("me server, you jane.")
|
||||
_open_server()
|
||||
|
||||
func _open_server() -> void:
|
||||
_peer.create_server(_port)
|
||||
get_tree().get_multiplayer().multiplayer_peer = _peer
|
||||
_write_line("created server at port: {port}".format({"port": _port}))
|
||||
|
||||
func _write_line(str: String) -> void:
|
||||
#text_output.text += str + "\n"
|
||||
print(str)
|
||||
|
||||
func _on_peer_connected(id: int) -> void:
|
||||
_write_line("peer connected: {peer_id}".format({"peer_id": id}))
|
||||
@@ -0,0 +1 @@
|
||||
uid://bbrx5vsfnm8c8
|
||||
@@ -0,0 +1,25 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://derhsnqg6p1lb"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bbrx5vsfnm8c8" path="res://screens/server.gd" id="1_mesmk"]
|
||||
|
||||
[sub_resource type="SystemFont" id="SystemFont_mesmk"]
|
||||
font_names = PackedStringArray("IBM Plex Mono")
|
||||
font_weight = 500
|
||||
|
||||
[node name="Server" type="Control" node_paths=PackedStringArray("text_output")]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_mesmk")
|
||||
text_output = NodePath("Label")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 20.0
|
||||
offset_top = 20.0
|
||||
offset_right = 1900.0
|
||||
offset_bottom = 1060.0
|
||||
theme_override_fonts/font = SubResource("SystemFont_mesmk")
|
||||
@@ -0,0 +1,10 @@
|
||||
extends Control
|
||||
|
||||
#func _ready() -> void:
|
||||
#_on_server_button_pressed()
|
||||
|
||||
func _on_client_button_pressed() -> void:
|
||||
get_tree().change_scene_to_file("uid://cgffw8lmsypov")
|
||||
|
||||
func _on_server_button_pressed() -> void:
|
||||
get_tree().change_scene_to_file("uid://derhsnqg6p1lb")
|
||||
@@ -0,0 +1 @@
|
||||
uid://ck2vokm0mc23h
|
||||
@@ -0,0 +1,60 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://ulnxbtq8mny1"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ck2vokm0mc23h" path="res://screens/test.gd" id="1_gb08i"]
|
||||
|
||||
[node name="Test" 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_gb08i")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 610.0
|
||||
offset_top = 190.0
|
||||
offset_right = 650.0
|
||||
offset_bottom = 213.0
|
||||
text = "Test"
|
||||
|
||||
[node name="Label2" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = -1
|
||||
anchor_right = 0.132
|
||||
anchor_bottom = 0.28
|
||||
offset_left = 475.0
|
||||
offset_top = 460.0
|
||||
offset_right = 261.56
|
||||
offset_bottom = 180.6
|
||||
text = "feedback"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 139.0
|
||||
offset_top = 207.0
|
||||
offset_right = 440.0
|
||||
offset_bottom = 271.0
|
||||
|
||||
[node name="ClientButton" type="Button" parent="HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "be client"
|
||||
|
||||
[node name="ServerButton" type="Button" parent="HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "make server"
|
||||
|
||||
[node name="Label3" type="Label" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = -1
|
||||
anchor_right = 0.132
|
||||
anchor_bottom = 0.28
|
||||
offset_left = 456.0
|
||||
offset_top = 510.0
|
||||
offset_right = 273.56
|
||||
offset_bottom = 230.6
|
||||
text = "feedback"
|
||||
|
||||
[connection signal="pressed" from="HBoxContainer/ClientButton" to="." method="_on_client_button_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer/ServerButton" to="." method="_on_server_button_pressed"]
|
||||
@@ -0,0 +1,194 @@
|
||||
from twisted.internet.protocol import DatagramProtocol
|
||||
from twisted.internet import reactor
|
||||
from time import sleep
|
||||
|
||||
import sys
|
||||
|
||||
def address_to_string(address):
|
||||
ip, port = address
|
||||
return ':'.join([ip, str(port)])
|
||||
|
||||
class ServerProtocol(DatagramProtocol):
|
||||
|
||||
def __init__(self):
|
||||
self.active_sessions: dict[Session] = {}
|
||||
self.registered_clients: dict[Client] = {}
|
||||
|
||||
# Checks whether a client with the given client_id is already registered.
|
||||
def is_client_registered(self, client_id):
|
||||
return client_id in self.registered_clients
|
||||
|
||||
# Checks if a session has already been registered with the given session_id.
|
||||
def session_exists(self, session_id) -> bool:
|
||||
return session_id in self.active_sessions
|
||||
|
||||
# Creates a new session for players to join.
|
||||
def create_session(self, session_id, host_client_id) -> int:
|
||||
if self.session_exists(session_id):
|
||||
# Tried to create existing session
|
||||
return 1
|
||||
|
||||
self.active_sessions[session_id] = Session(session_id, host_client_id, self)
|
||||
return 0
|
||||
|
||||
# Closes an existing session. Must disconnect all clients manually before calling this!
|
||||
def close_session(self, s_id):
|
||||
try:
|
||||
del self.active_sessions[s_id]
|
||||
except KeyError:
|
||||
print("Tried to terminate non-existing session")
|
||||
|
||||
# Registers a client and connects them to a given session.
|
||||
def register_client(self, session_id, client_id, client_name, client_ip, client_port) -> int:
|
||||
if self.is_client_registered(client_id):
|
||||
print("Client %s is already registered." % [client_id])
|
||||
return 1
|
||||
|
||||
if not self.session_exists(session_id):
|
||||
print("Client registered for non-existing session")
|
||||
return 2
|
||||
|
||||
if len(self.active_sessions[session_id].registered_clients) >= 2:
|
||||
print("Trying to join full session")
|
||||
return 3
|
||||
|
||||
new_client = Client(session_id, client_id, client_name, client_ip, client_port)
|
||||
self.registered_clients[client_id] = new_client
|
||||
self.active_sessions[session_id].register_client(new_client)
|
||||
|
||||
return 0
|
||||
|
||||
# Disconnects a client and removes them from the registered_clients.
|
||||
def disconnect_client(self, session_id, client_id):
|
||||
try:
|
||||
del self.registered_clients[client_id]
|
||||
self.active_sessions[session_id].remove_client(client_id)
|
||||
except KeyError:
|
||||
print("Tried to disconnect unregistered client %s." % [client_id])
|
||||
|
||||
# Checks whether the given client owns any session. Returns the session ID if true.
|
||||
# Returns an empty string otherwise.
|
||||
def owns_session(self, client_id) -> str:
|
||||
for session_id in self.active_sessions:
|
||||
if self.active_sessions[session_id].host_client_id == client_id:
|
||||
return session_id
|
||||
return ""
|
||||
|
||||
# Sends a message to a client specified by their address.
|
||||
def send_message(self, msg, address):
|
||||
self.transport.write(bytes(msg, "utf-8"), address)
|
||||
|
||||
# Executed when data is received from a client.
|
||||
def datagramReceived(self, datagram, address):
|
||||
"""Handle incoming datagram messages."""
|
||||
print(datagram)
|
||||
data_string = datagram.decode("utf-8")
|
||||
msg_type = data_string[:2]
|
||||
|
||||
print(address)
|
||||
|
||||
client_ip, client_port = address
|
||||
split_data = data_string.split(":")
|
||||
|
||||
if msg_type == "cr":
|
||||
# create lobby
|
||||
error = self.create_session(split_data[1], split_data[2])
|
||||
|
||||
if error == 1:
|
||||
# tried to create existing session
|
||||
print("Could not create session; already exists")
|
||||
self.transport.write(bytes('c1', "utf-8"), address)
|
||||
return
|
||||
|
||||
# TODO no error handling for register_client here yet
|
||||
print(self.register_client(split_data[1], split_data[2], split_data[3], client_ip, client_port))
|
||||
print(client_port)
|
||||
print("CLIENT PORT")
|
||||
print("successfully created session and registered client")
|
||||
self.transport.write(bytes('c0', "utf-8"), address)
|
||||
|
||||
|
||||
elif msg_type == "jn":
|
||||
# join lobby
|
||||
error = self.register_client(split_data[1], split_data[2], split_data[3], client_ip, client_port)
|
||||
print(client_port)
|
||||
print("CLIENT PORT")
|
||||
|
||||
if error == 1:
|
||||
# client already registered
|
||||
self.send_message('j1', address)
|
||||
return
|
||||
elif error == 2:
|
||||
# session does not exist
|
||||
self.send_message('j2', address)
|
||||
return
|
||||
elif error == 3:
|
||||
# session full
|
||||
self.send_message('j3', address)
|
||||
return
|
||||
|
||||
self.send_message('j0', address)
|
||||
print("joined successfully")
|
||||
|
||||
elif msg_type == "lv":
|
||||
session_id = split_data[1]
|
||||
leaving_client_id = split_data[2]
|
||||
owned_session = self.owns_session(leaving_client_id)
|
||||
if owned_session == "":
|
||||
# client is only connected to a session
|
||||
self.disconnect_client(session_id, leaving_client_id)
|
||||
print("disconnected client from session")
|
||||
else:
|
||||
# client owns a session
|
||||
# disconnect all clients
|
||||
clients_to_delete = self.active_sessions[session_id].registered_clients.copy()
|
||||
for client in clients_to_delete:
|
||||
print(clients_to_delete)
|
||||
print(client)
|
||||
client_address = (client.client_ip, client.client_port)
|
||||
print(client_address)
|
||||
self.send_message('ex', client_address)
|
||||
self.disconnect_client(client.session_id, client.client_id)
|
||||
|
||||
self.close_session(session_id)
|
||||
print("host gone; disconnected clients and closed session")
|
||||
|
||||
class Session:
|
||||
|
||||
def __init__(self, session_id, host_client_id, server):
|
||||
self.id = session_id
|
||||
self.host_client_id = host_client_id
|
||||
self.server = server
|
||||
self.registered_clients: list[Client] = []
|
||||
|
||||
# Registers a client in the session.
|
||||
def register_client(self, client):
|
||||
if client in self.registered_clients:
|
||||
# Client is already registered
|
||||
return
|
||||
|
||||
self.registered_clients.append(client)
|
||||
|
||||
def remove_client(self, client_id):
|
||||
for client in self.registered_clients:
|
||||
if client.client_id == client_id:
|
||||
self.registered_clients.remove(client)
|
||||
|
||||
class Client:
|
||||
|
||||
def __init__(self, session_id, client_id, client_name, client_ip, client_port):
|
||||
self.session_id = session_id
|
||||
self.client_id = client_id
|
||||
self.client_name = client_name
|
||||
self.client_ip = client_ip
|
||||
self.client_port = client_port
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: ./server.py PORT")
|
||||
sys.exit(1)
|
||||
|
||||
port = int(sys.argv[1])
|
||||
reactor.listenUDP(port, ServerProtocol())
|
||||
print('Listening on *:%d' % (port))
|
||||
reactor.run()
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
class_name WebClient
|
||||
extends Node
|
||||
|
||||
@export var name_input: LineEdit
|
||||
@export var session_code_input: LineEdit
|
||||
@export var output: Label
|
||||
@export var create_lobby_button: Button
|
||||
@export var join_lobby_button: Button
|
||||
@export var disconnect_lobby_button: Button
|
||||
|
||||
var _peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
|
||||
var _address: String = "127.0.0.1"
|
||||
var _port: int = 9974
|
||||
|
||||
var _udp: PacketPeerUDP = PacketPeerUDP.new()
|
||||
var _tcp = PacketPeerDTLS
|
||||
|
||||
var _session_id: String
|
||||
var _client_id: String
|
||||
var _client_name: String
|
||||
|
||||
var _is_in_lobby: bool = false
|
||||
|
||||
const MSG_CREATE_LOBBY: String = "cr"
|
||||
const MSG_JOIN_LOBBY: String = "jn"
|
||||
const MSG_LEAVE_LOBBY: String = "lv"
|
||||
|
||||
const REMOTE_CREATE_SESSION_SUCCESS: String = "c0"
|
||||
const REMOTE_ERR_CREATE_SESSION: String = "c1"
|
||||
const REMOTE_JOIN_SESSION_SUCCESS: String = "j0"
|
||||
const REMOTE_JOIN_SESSION_DUPLICATE: String = "j1"
|
||||
const REMOTE_JOIN_SESSION_MISSING: String = "j2"
|
||||
const REMOTE_JOIN_SESSION_FULL: String = "j3"
|
||||
const REMOTE_EXIT_SESSION: String = "ex"
|
||||
|
||||
func _ready() -> void:
|
||||
_write_output("me client, you jane.")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if _udp.get_available_packet_count() > 0:
|
||||
var packet_str = _udp.get_packet().get_string_from_ascii()
|
||||
print(packet_str)
|
||||
match packet_str.substr(0, 2):
|
||||
# Session creation
|
||||
REMOTE_CREATE_SESSION_SUCCESS:
|
||||
_write_output("Created and joined lobby successfully.")
|
||||
_write_output("Lobby code: {session_id}".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
_write_output("Your player code: {client_id}".format({
|
||||
"client_id": _client_id
|
||||
}))
|
||||
_on_lobby_connected()
|
||||
|
||||
REMOTE_ERR_CREATE_SESSION:
|
||||
_write_output("Could not create lobby.")
|
||||
_write_output("A lobby with the code {session_id} already exists.".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
|
||||
REMOTE_JOIN_SESSION_SUCCESS:
|
||||
_write_output("Joined lobby successfully.")
|
||||
_write_output("Your player code: {client_id}".format({"client_id": _client_id}))
|
||||
_on_lobby_connected()
|
||||
|
||||
# Session joining
|
||||
REMOTE_JOIN_SESSION_DUPLICATE:
|
||||
_write_output("Could not join lobby {session_id}.".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
_write_output("A player with the code {client_id} is already registered in the lobby.".format({
|
||||
"client_id": _client_id,
|
||||
}))
|
||||
|
||||
REMOTE_JOIN_SESSION_MISSING:
|
||||
_write_output("No lobby exists with the code {session_id}.".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
|
||||
REMOTE_JOIN_SESSION_FULL:
|
||||
_write_output("Could not join lobby {session_id}.".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
_write_output("The lobby has reached the maximum player count.")
|
||||
|
||||
# Session exit
|
||||
REMOTE_EXIT_SESSION:
|
||||
_on_lobby_disconnected()
|
||||
|
||||
func _exit_tree() -> void:
|
||||
_disconnect_from_lobby()
|
||||
|
||||
func _generate_code() -> String:
|
||||
# use a local randomized RNG to keep the global RNG reproducible
|
||||
var rng = RandomNumberGenerator.new()
|
||||
rng.randomize()
|
||||
var length = 6
|
||||
var result = ''
|
||||
for _n in range(length):
|
||||
var ascii = rng.randi_range(0, 25) + 65
|
||||
result += '%c' % ascii
|
||||
return result
|
||||
|
||||
func _on_peer_connected(id: int) -> void:
|
||||
$Label.text += "connected to id: " + str(id)
|
||||
|
||||
func _get_client_string(remote_code: String, session_id: String, client_id: String, client_name: String) -> PackedByteArray:
|
||||
return "{remote_code}:{session_id}:{client_id}:{client_name}".format({
|
||||
"remote_code": remote_code,
|
||||
"session_id": session_id,
|
||||
"client_id": client_id,
|
||||
"client_name": client_name,
|
||||
}).to_utf8_buffer()
|
||||
|
||||
func _disconnect_from_lobby() -> void:
|
||||
if _is_in_lobby:
|
||||
_udp.put_packet(_get_client_string(MSG_LEAVE_LOBBY, _session_id, _client_id, _client_name))
|
||||
_udp.close()
|
||||
|
||||
func _write_output(text: String) -> void:
|
||||
output.text += text + "\n"
|
||||
|
||||
func _on_lobby_connected() -> void:
|
||||
_is_in_lobby = true
|
||||
create_lobby_button.disabled = true
|
||||
join_lobby_button.disabled = true
|
||||
disconnect_lobby_button.disabled = false
|
||||
|
||||
func _on_lobby_disconnected() -> void:
|
||||
_write_output("Connection with lobby {session_id} ended.".format({
|
||||
"session_id": _session_id
|
||||
}))
|
||||
_udp.close()
|
||||
_is_in_lobby = false
|
||||
name_input.editable = true
|
||||
session_code_input.editable = true
|
||||
session_code_input.text = ""
|
||||
_session_id = ""
|
||||
create_lobby_button.disabled = false
|
||||
join_lobby_button.disabled = false
|
||||
disconnect_lobby_button.disabled = true
|
||||
|
||||
# Create new session
|
||||
func _on_create_lobby_button_pressed() -> void:
|
||||
_udp.set_dest_address(_address, _port)
|
||||
_session_id = _generate_code()
|
||||
session_code_input.text = _session_id
|
||||
name_input.editable = false
|
||||
session_code_input.editable = false
|
||||
_client_id = _generate_code()
|
||||
_client_name = name_input.text.strip_edges()
|
||||
|
||||
_udp.put_packet(_get_client_string(MSG_CREATE_LOBBY, _session_id, _client_id, _client_name))
|
||||
|
||||
# Connect to existing session
|
||||
func _on_join_lobby_button_pressed() -> void:
|
||||
_udp.set_dest_address(_address, _port)
|
||||
name_input.editable = false
|
||||
session_code_input.editable = false
|
||||
|
||||
_session_id = session_code_input.text.strip_edges()
|
||||
_client_id = _generate_code()
|
||||
_client_name = name_input.text.strip_edges()
|
||||
|
||||
_udp.put_packet(_get_client_string(MSG_JOIN_LOBBY, _session_id, _client_id, _client_name))
|
||||
|
||||
func _on_disconnect_lobby_button_pressed() -> void:
|
||||
_disconnect_from_lobby()
|
||||
_on_lobby_disconnected()
|
||||
@@ -0,0 +1 @@
|
||||
uid://bfaxxdr7v0emr
|
||||
Reference in New Issue
Block a user