New network manager test

This commit is contained in:
Chris Bell 2024-12-13 10:47:42 -06:00
parent 707165373b
commit 6650820429
9 changed files with 423 additions and 26 deletions

View File

@ -1,6 +1,6 @@
extends Control extends Control
@export var network_manager: NetworkManager @export var network_manager: OldnetworkManager
@export var host_button: Button @export var host_button: Button
@export var join_button: Button @export var join_button: Button

View File

@ -1,28 +1,18 @@
[gd_scene load_steps=4 format=3 uid="uid://dfa8n5rw2qpfd"] [gd_scene load_steps=2 format=3 uid="uid://dfa8n5rw2qpfd"]
[ext_resource type="PackedScene" uid="uid://bpmn7t87tfk7f" path="res://assets/core/networking/old/old_network_manager.tscn" id="1_i1w5w"] [ext_resource type="PackedScene" uid="uid://bpmn7t87tfk7f" path="res://assets/core/networking/old/old_network_manager.tscn" id="1_i1w5w"]
[ext_resource type="Script" path="res://assets/core/networking/old/old_network_test_ui.gd" id="2_rbs4r"]
[ext_resource type="PackedScene" uid="uid://biryul3n6thlw" path="res://assets/core/networking/old/old_user_box_prefab.tscn" id="3_if51w"]
[node name="Test-lobby" type="Node"] [node name="Test-lobby" type="Node"]
[node name="NetworkManager" parent="." instance=ExtResource("1_i1w5w")] [node name="NetworkManager" parent="." instance=ExtResource("1_i1w5w")]
[node name="UiRoot" type="Control" parent="." node_paths=PackedStringArray("network_manager", "host_button", "join_button", "lobby_id", "hosted_lobby_id", "users_list")] [node name="UiRoot" type="Control" parent="."]
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("2_rbs4r")
network_manager = NodePath("../NetworkManager")
host_button = NodePath("Panel/HBoxContainer/VBoxContainer/Host")
join_button = NodePath("Panel/HBoxContainer/VBoxContainer/Join")
lobby_id = NodePath("Panel/HBoxContainer/VBoxContainer/LobbyID")
hosted_lobby_id = NodePath("Panel/HBoxContainer/VBoxContainer/HostedLobbyID")
users_list = NodePath("Panel/HBoxContainer/UsersList")
user_box_prefab = ExtResource("3_if51w")
[node name="Panel" type="Panel" parent="UiRoot"] [node name="Panel" type="Panel" parent="UiRoot"]
layout_mode = 1 layout_mode = 1

View File

@ -1,4 +1,4 @@
class_name NetworkManager class_name OldnetworkManager
extends Node extends Node
const PACKET_READ_LIMIT: int = 32 const PACKET_READ_LIMIT: int = 32

View File

@ -1,4 +1,6 @@
[gd_scene format=3 uid="uid://7t1x82gvrw8a"] [gd_scene load_steps=2 format=3 uid="uid://7t1x82gvrw8a"]
[ext_resource type="Script" path="res://assets/core/networking/scripts/lobby.gd" id="1_o4fbq"]
[node name="Lobby" type="Control"] [node name="Lobby" type="Control"]
layout_mode = 3 layout_mode = 3
@ -7,3 +9,52 @@ anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("1_o4fbq")
[node name="Panel" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Buttons" type="VBoxContainer" parent="Panel/HBoxContainer"]
custom_minimum_size = Vector2(500, 0)
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 4
[node name="Host" type="Button" parent="Panel/HBoxContainer/Buttons"]
layout_mode = 2
size_flags_vertical = 4
text = "Host Lobby"
[node name="HBoxContainer" type="HBoxContainer" parent="Panel/HBoxContainer/Buttons"]
layout_mode = 2
[node name="LineEdit" type="LineEdit" parent="Panel/HBoxContainer/Buttons/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Join" type="Button" parent="Panel/HBoxContainer/Buttons/HBoxContainer"]
custom_minimum_size = Vector2(90, 0)
layout_mode = 2
text = "Join"
[node name="Leave" type="Button" parent="Panel/HBoxContainer/Buttons"]
layout_mode = 2
disabled = true
text = "Leave Lobby"
[node name="PlayerList" type="VBoxContainer" parent="Panel/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3

View File

@ -3,6 +3,8 @@
[ext_resource type="Texture2D" uid="uid://fwub8fvl2u4i" path="res://addons/ingameconsole/ps1hagrid.png" id="1_gtutw"] [ext_resource type="Texture2D" uid="uid://fwub8fvl2u4i" path="res://addons/ingameconsole/ps1hagrid.png" id="1_gtutw"]
[node name="UserBox" type="HBoxContainer"] [node name="UserBox" type="HBoxContainer"]
offset_right = 610.0
offset_bottom = 128.0
[node name="PFP" type="TextureRect" parent="."] [node name="PFP" type="TextureRect" parent="."]
custom_minimum_size = Vector2(128, 128) custom_minimum_size = Vector2(128, 128)
@ -13,5 +15,6 @@ expand_mode = 1
[node name="Username" type="Label" parent="."] [node name="Username" type="Label" parent="."]
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 8 size_flags_horizontal = 3
text = "Hagrid 1" text = "Hagrid 1"
horizontal_alignment = 1

View File

@ -1,11 +1,312 @@
extends Node extends Node
const STEAM_APP_ID: int = 480
const PACKET_READ_LIMIT: int = 32
var lobby_data
var lobby_id: int = 0
var lobby_members: Array = []
var lobby_members_max: int = 10
var lobby_vote_kick: bool = false
var lobby_type: int = Steam.LOBBY_TYPE_PUBLIC
var steam_id: int = 0
var steam_username: String = ""
var avatar_texture_cache: Dictionary = {}
signal lobby_created(lobby_id: int)
signal lobby_joined(lobby_id: int)
signal user_joined_lobby(user_id: int)
signal user_left_lobby(user_id: int)
# Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
pass # Replace with function body. _init_steam()
# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta: float) -> void:
func _process(delta: float) -> void: Steam.run_callbacks()
if lobby_id > 0:
read_all_p2p_packets()
func _init_steam() -> void:
var init_result = Steam.steamInitEx(true, STEAM_APP_ID)
print("Steam Init Result: " + str(init_result))
if init_result['status'] > 0:
printerr("Steam failed to initialize, shutting down: " + str(init_result))
#get_tree().quit()
steam_id = Steam.getSteamID()
steam_username = Steam.getFriendPersonaName(steam_id)
Steam.p2p_session_request.connect(_on_p2p_session_request)
Steam.p2p_session_connect_fail.connect(_on_p2p_session_connect_fail)
Steam.join_requested.connect(_on_lobby_join_requested)
Steam.lobby_chat_update.connect(_on_lobby_chat_update)
Steam.lobby_created.connect(_on_lobby_created)
Steam.lobby_data_update.connect(_on_lobby_data_update)
Steam.lobby_invite.connect(_on_lobby_invite)
Steam.lobby_joined.connect(_on_lobby_joined)
Steam.lobby_match_list.connect(_on_lobby_match_list)
Steam.lobby_message.connect(_on_lobby_message)
Steam.persona_state_change.connect(_on_persona_change)
func _on_lobby_join_requested(this_lobby_id: int, friend_id: int):
var owner_name: String = Steam.getFriendPersonaName(friend_id)
print("Trying to join " + owner_name + "'s lobby...")
join_lobby(this_lobby_id)
func _on_lobby_chat_update(this_lobby_id: int, change_id: int, making_change_id: int, chat_state: int) -> void:
var changer_name: String = Steam.getFriendPersonaName(change_id)
# If a player has joined the lobby
if chat_state == Steam.CHAT_MEMBER_STATE_CHANGE_ENTERED:
print("%s has joined the lobby." % changer_name)
elif chat_state == Steam.CHAT_MEMBER_STATE_CHANGE_LEFT:
print("%s has left the lobby." % changer_name)
elif chat_state == Steam.CHAT_MEMBER_STATE_CHANGE_KICKED:
print("%s has been kicked from the lobby." % changer_name)
elif chat_state == Steam.CHAT_MEMBER_STATE_CHANGE_BANNED:
print("%s has been banned from the lobby." % changer_name)
else:
print("%s did... something." % changer_name)
get_lobby_members()
func _on_lobby_created(connect: int, this_lobby_id: int) -> void:
if connect == 1:
lobby_id = this_lobby_id
lobby_created.emit(lobby_id)
print("Lobby created with ID: " + str(lobby_id))
Steam.setLobbyJoinable(lobby_id, true)
Steam.setLobbyData(lobby_id, "name", str(steam_username) + "'s Lobby")
var set_relay: bool = Steam.allowP2PPacketRelay(true)
func _on_lobby_data_update():
pass pass
func _on_lobby_invite():
pass
func _on_lobby_joined(this_lobby_id: int, _permissions: int, response: int) -> void:
if response == Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS:
lobby_id = this_lobby_id
get_lobby_members()
make_p2p_handshake()
lobby_joined.emit(lobby_id)
else:
var fail_reason: String
match response:
Steam.CHAT_ROOM_ENTER_RESPONSE_DOESNT_EXIST: fail_reason = "This lobby no longer exists."
Steam.CHAT_ROOM_ENTER_RESPONSE_NOT_ALLOWED: fail_reason = "You don't have permission to join this lobby."
Steam.CHAT_ROOM_ENTER_RESPONSE_FULL: fail_reason = "The lobby is now full."
Steam.CHAT_ROOM_ENTER_RESPONSE_ERROR: fail_reason = "Uh... something unexpected happened!"
Steam.CHAT_ROOM_ENTER_RESPONSE_BANNED: fail_reason = "You are banned from this lobby."
Steam.CHAT_ROOM_ENTER_RESPONSE_LIMITED: fail_reason = "You cannot join due to having a limited account."
Steam.CHAT_ROOM_ENTER_RESPONSE_CLAN_DISABLED: fail_reason = "This lobby is locked or disabled."
Steam.CHAT_ROOM_ENTER_RESPONSE_COMMUNITY_BAN: fail_reason = "This lobby is community locked."
Steam.CHAT_ROOM_ENTER_RESPONSE_MEMBER_BLOCKED_YOU: fail_reason = "A user in the lobby has blocked you from joining."
Steam.CHAT_ROOM_ENTER_RESPONSE_YOU_BLOCKED_MEMBER: fail_reason = "A user you have blocked is in the lobby."
print("Failed to join this chat room: %s" % fail_reason)
func _on_lobby_match_list():
pass
func _on_lobby_message():
pass
func _on_persona_change(this_steam_id: int, _flags: int) -> void:
if lobby_id > 0:
print("User (%s) had information change, updating lobby list." % str(this_steam_id))
get_lobby_members()
func _on_p2p_session_request(remote_id: int):
var this_requester: String = Steam.getFriendPersonaName(remote_id)
print("P2P session request from: " + this_requester)
Steam.acceptP2PSessionWithUser(remote_id)
make_p2p_handshake()
func _on_p2p_session_connect_fail(steam_id: int, session_error: int) -> void:
# If no error was given
if session_error == 0:
print("WARNING: Session failure with %s: no error given" % steam_id)
# Else if target user was not running the same game
elif session_error == 1:
print("WARNING: Session failure with %s: target user not running the same game" % steam_id)
# Else if local user doesn't own app / game
elif session_error == 2:
print("WARNING: Session failure with %s: local user doesn't own app / game" % steam_id)
# Else if target user isn't connected to Steam
elif session_error == 3:
print("WARNING: Session failure with %s: target user isn't connected to Steam" % steam_id)
# Else if connection timed out
elif session_error == 4:
print("WARNING: Session failure with %s: connection timed out" % steam_id)
# Else if unused
elif session_error == 5:
print("WARNING: Session failure with %s: unused" % steam_id)
# Else no known error
else:
print("WARNING: Session failure with %s: unknown error %s" % [steam_id, session_error])
func host_lobby():
if lobby_id == 0:
Steam.createLobby(lobby_type, lobby_members_max)
else:
printerr("Cannot host lobby, already in a lobby")
func join_lobby(this_lobby_id: int):
print("Attempting to join lobby: " + str(this_lobby_id))
lobby_members.clear()
Steam.joinLobby(this_lobby_id)
func leave_lobby():
if lobby_id != 0:
Steam.leaveLobby(lobby_id)
lobby_id = 0
for this_member in lobby_members:
if this_member["steam_id"] != steam_id:
Steam.closeP2PSessionWithUser(this_member["steam_id"])
lobby_members.clear()
func get_lobby_members():
lobby_members.clear()
var member_count: int = Steam.getNumLobbyMembers(lobby_id)
for this_member in range(0, member_count):
var member_steam_id: int = Steam.getLobbyMemberByIndex(lobby_id, this_member)
var member_steam_name: String = Steam.getFriendPersonaName(member_steam_id)
lobby_members.append({"steam_id":member_steam_id, "steam_name":member_steam_name})
user_joined_lobby.emit(member_steam_id)
await request_player_avatar(member_steam_id)
func make_p2p_handshake():
print("Sending p2p handshake to the lobby...")
send_p2p_packet(0, {"message":"handshake", "from":steam_id})
func send_p2p_packet(target: int, packet_data: Dictionary) -> void:
# Set the send_type and channel
var send_type: int = Steam.P2P_SEND_RELIABLE
var channel: int = 0
# Create a data array to send the data through
var this_data: PackedByteArray
# Compress the PackedByteArray we create from our dictionary using the GZIP compression method
var compressed_data: PackedByteArray = var_to_bytes(packet_data).compress(FileAccess.COMPRESSION_GZIP)
this_data.append_array(compressed_data)
# If sending a packet to everyone
if target == 0:
# If there is more than one user, send packets
if lobby_members.size() > 1:
# Loop through all members that aren't you
for this_member in lobby_members:
if this_member['steam_id'] != steam_id:
Steam.sendP2PPacket(this_member['steam_id'], this_data, send_type, channel)
# Else send it to someone specific
else:
Steam.sendP2PPacket(target, this_data, send_type, channel)
func read_all_p2p_packets(read_count: int = 0):
if read_count >= PACKET_READ_LIMIT:
return
if Steam.getAvailableP2PPacketSize(0) > 0:
read_p2p_packet()
read_all_p2p_packets(read_count + 1)
func read_p2p_packet() -> void:
var packet_size: int = Steam.getAvailableP2PPacketSize(0)
# There is a packet
if packet_size > 0:
var this_packet: Dictionary = Steam.readP2PPacket(packet_size, 0)
if this_packet.is_empty() or this_packet == null:
print("WARNING: read an empty packet with non-zero size!")
# Get the remote user's ID
var packet_sender: int = this_packet['remote_steam_id']
# Make the packet data readable
var packet_code: PackedByteArray = this_packet['data']
# Decompress the array before turning it into a useable dictionary
var readable_data: Dictionary = bytes_to_var(packet_code.decompress_dynamic(-1, FileAccess.COMPRESSION_GZIP))
# Print the packet to output
print("Packet: %s" % readable_data)
func request_player_avatar(user_id: int, size: int = 128) -> void:
if avatar_texture_cache.has(user_id):
return
var avatar_texture: ImageTexture = null
Steam.getPlayerAvatar(Steam.AVATAR_LARGE, user_id)
print("Attempting to get avatar for " + Steam.getFriendPersonaName(user_id) + ".....")
Steam.avatar_loaded.connect(func(loaded_user_id: int, avatar_size: int, avatar_buffer: PackedByteArray):
if loaded_user_id == user_id:
var avatar_image: Image = Image.create_from_data(avatar_size, avatar_size, false, Image.FORMAT_RGBA8, avatar_buffer)
if avatar_size != size:
avatar_image.resize(size, size, Image.INTERPOLATE_LANCZOS)
avatar_texture = ImageTexture.create_from_image(avatar_image)
avatar_texture_cache[user_id] = avatar_texture
)
# Wait for the avatar to load asynchronously
await get_tree().process_frames(2)
if avatar_texture == null:
printerr("Could not load image for user: " + Steam.getFriendPersonaName(user_id))
func get_player_avatar(user_id: int) -> ImageTexture:
if avatar_texture_cache.has(user_id):
return avatar_texture_cache[user_id]
else:
return await request_player_avatar(user_id)

View File

@ -1,11 +1,62 @@
extends Control extends Control
@export var host_button: Button
@export var join_button: Button
@export var leave_button: Button
@export var lobby_id: LineEdit
@export var user_list_box: VBoxContainer
@export var user_box_prefab: PackedScene
# Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
pass # Replace with function body. host_button.pressed.connect(_on_host)
join_button.pressed.connect(_on_join)
leave_button.pressed.connect(_on_leave)
NetworkManager.lobby_created.connect(_on_lobby_created)
NetworkManager.lobby_joined.connect(_on_lobby_joined)
NetworkManager.user_joined_lobby.connect(_on_user_joined_lobby)
NetworkManager.user_left_lobby.connect(_on_user_left_lobby)
# Called every frame. 'delta' is the elapsed time since the previous frame. func _on_host():
func _process(delta: float) -> void: NetworkManager.host_lobby()
pass host_button.disabled = true
join_button.disabled = true
leave_button.disabled = false
lobby_id.disabled = true
lobby_id.text = str(NetworkManager.lobby_id)
func _on_join():
NetworkManager.join_lobby(int(lobby_id.text))
host_button.disabled = true
join_button.disabled = true
leave_button.disabled = false
lobby_id.disabled = true
func _on_leave():
NetworkManager.leave_lobby()
func _on_lobby_created():
print("Lobby created")
func _on_lobby_joined():
print("Lobby joined")
func _on_user_joined_lobby(user_id:int):
var user_box = user_box_prefab.instance()
user_box.get_node("Username").text = str(user_id)
user_list_box.add_child(user_box)
user_box.get_node("PFP").texture = await NetworkManager.get_player_avatar(user_id)
func _on_user_left_lobby(user_id:int):
for child in user_list_box.get_children():
if child.get_node("Username").text == str(user_id):
user_list_box.remove_child(child)
break

View File

@ -1,6 +1,6 @@
class_name Player extends CharacterBody3D class_name Player extends CharacterBody3D
var network_manager: NetworkManager var network_manager: OldnetworkManager
var player_tag: Label3D var player_tag: Label3D
var username: String = "" var username: String = ""

View File

@ -18,6 +18,7 @@ config/icon="res://assets/icon.png"
[autoload] [autoload]
GameConsole="*res://addons/ingameconsole/GameConsole.tscn" GameConsole="*res://addons/ingameconsole/GameConsole.tscn"
NetworkManager="*res://assets/core/networking/scripts/NetworkManager.gd"
[debug] [debug]