Inital project

This commit is contained in:
2026-05-22 23:25:13 -05:00
commit b7defbdbfc
243 changed files with 5718 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
extends Node
const BALL = preload("uid://dpcnrigmslqkt")
var current_level: Node
var chat_node: Chat
@rpc("any_peer", "call_remote", "reliable")
func request_spawn_ball(pos: Vector3):
if is_multiplayer_authority():
_spawn_ball(pos, multiplayer.get_remote_sender_id())
func _spawn_ball(pos: Vector3, sender_id: int):
var new_ball: Node3D = BALL.instantiate()
new_ball.name = "Ball_%d_%d" % [sender_id, randi()]
current_level.add_child(new_ball, true)
new_ball.global_position = pos

View File

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

View File

@@ -0,0 +1,175 @@
extends Node
const PLAYER = preload("uid://cq6ovfsdvnt40")
const LOADING_SCREEN = preload("uid://38t27mxycd35")
var enet_peer := ENetMultiplayerPeer.new()
var port = 9999
var is_steam_lobby: bool = false
var steam_lobby_id: int = 0
var steam_peer := SteamMultiplayerPeer.new()
var is_host_steam: bool = false
var is_joining_steam: bool = false
var loading_screen: LoadingScreen
var player_list: Dictionary[int, Player]
var ip_username: String = "Username"
var ip_avatar: ImageTexture
func create_loading_screen(label_text: String = "Joining server..."):
loading_screen = LOADING_SCREEN.instantiate()
get_tree().current_scene.add_child.call_deferred(loading_screen, true)
loading_screen.cancel_pressed.connect(func(): leave_server())
loading_screen.loading_label.text = label_text
loading_screen.show()
func _connect_multiplayer_signals(is_server: bool):
multiplayer.peer_connected.connect(add_player)
multiplayer.peer_disconnected.connect(remove_player)
if not is_server:
multiplayer.connected_to_server.connect(_on_connected_to_server)
func start_server(username: String, avatar: ImageTexture):
is_steam_lobby = false
ip_username = username
ip_avatar = avatar
enet_peer.create_server(port)
multiplayer.multiplayer_peer = enet_peer
_connect_multiplayer_signals(true)
add_player(1)
func start_steam_lobby():
Steam.lobby_created.connect(_on_steam_lobby_created)
Steam.createLobby(Steam.LOBBY_TYPE_PUBLIC, 10)
is_host_steam = true
func _on_steam_lobby_created(result: int, lobby_id: int) -> void:
if result != Steam.Result.RESULT_OK:
push_error("Could not create lobby: " + str(result))
return
steam_lobby_id = lobby_id
steam_peer.server_relay = true
steam_peer.create_host()
multiplayer.multiplayer_peer = steam_peer
_connect_multiplayer_signals(true)
is_steam_lobby = true
add_player(1)
print("Lobby created. ID: " + str(lobby_id))
print("Steam ID for host: " + str(steam_peer.get_steam_id_for_peer_id(1)))
print("Steam ID for host (from autoload): " + str(Steamworks.steam_id))
func join_server(ip: String, username: String, avatar: ImageTexture):
is_steam_lobby = false
ip_username = username
ip_avatar = avatar
enet_peer.create_client(ip, port)
multiplayer.multiplayer_peer = enet_peer
_connect_multiplayer_signals(false)
create_loading_screen()
func join_steam_lobby(lobby_id: int):
Steam.lobby_joined.connect(_on_join_steam_lobby)
is_joining_steam = true
Steam.joinLobby(lobby_id)
create_loading_screen("Joining steam lobby...")
func _on_join_steam_lobby(lobby_id: int, permission: int, locked: bool, response: int) -> void:
if not is_joining_steam:
return
steam_lobby_id = lobby_id
steam_peer.server_relay = true
var result := steam_peer.create_client(Steam.getLobbyOwner(lobby_id))
if result != 0:
push_error("Could not join lobby: " + str(result))
return
multiplayer.multiplayer_peer = steam_peer
_connect_multiplayer_signals(false)
is_joining_steam = false
is_steam_lobby = true
func _on_connected_to_server():
add_player(multiplayer.get_unique_id())
if is_steam_lobby:
set_player_details_steam.rpc(multiplayer.get_unique_id(), Steamworks.steam_id)
else:
set_player_details_ip.rpc(multiplayer.get_unique_id(), ip_username, ip_avatar.get_image().save_png_to_buffer())
loading_screen.queue_free()
@rpc("any_peer", "call_local")
func set_player_details_steam(peer_id: int, steam_id: int):
if player_list.has(peer_id):
await player_list[peer_id].set_player_info_steam(steam_id)
@rpc("any_peer", "call_local")
func set_player_details_ip(peer_id: int, username: String, avatar_bytes: PackedByteArray):
if player_list.has(peer_id):
await player_list[peer_id].set_player_info_ip(username, avatar_bytes)
func add_player(peer_id: int):
var new_player: Player = PLAYER.instantiate()
new_player.name = str(peer_id)
get_tree().current_scene.add_child(new_player, true)
player_list[peer_id] = new_player
if is_steam_lobby and player_list.has(multiplayer.get_unique_id()):
set_player_details_steam.rpc(multiplayer.get_unique_id(), Steamworks.steam_id)
elif !is_steam_lobby and player_list.has(multiplayer.get_unique_id()):
set_player_details_ip.rpc(multiplayer.get_unique_id(), ip_username, ip_avatar.get_image().save_png_to_buffer())
func remove_player(peer_id: int):
if peer_id == 1:
leave_server()
return
if player_list.has(peer_id):
player_list[peer_id].queue_free()
player_list.erase(peer_id)
func leave_server():
if is_steam_lobby:
_cleanup_steam_signals()
_cleanup_multiplayer_signals()
multiplayer.multiplayer_peer.close()
multiplayer.multiplayer_peer = null
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
player_list.clear()
get_tree().reload_current_scene()
func _cleanup_multiplayer_signals():
if multiplayer.peer_connected.is_connected(add_player):
multiplayer.peer_connected.disconnect(add_player)
if multiplayer.peer_disconnected.is_connected(remove_player):
multiplayer.peer_disconnected.disconnect(remove_player)
if multiplayer.connected_to_server.is_connected(_on_connected_to_server):
multiplayer.connected_to_server.disconnect(_on_connected_to_server)
func _cleanup_steam_signals():
if Steam.lobby_created.is_connected(_on_steam_lobby_created):
Steam.lobby_created.disconnect(_on_steam_lobby_created)
if Steam.lobby_joined.is_connected(_on_join_steam_lobby):
Steam.lobby_joined.disconnect(_on_join_steam_lobby)

View File

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

View File

@@ -0,0 +1,39 @@
extends Node
var is_initalized: bool = false
var steam_id: int
var steam_username: String
var steam_avatar: ImageTexture
var tmp_avatar_image_texture: ImageTexture
func _ready() -> void:
if is_initalized: return
var response := Steam.steamInitEx()
if response["status"] != 0:
push_warning("Steam failed to initalize: " + str(response))
return
steam_id = Steam.getSteamID()
steam_username = Steam.getPersonaName()
steam_avatar = await get_player_avatar(steam_id)
print("Steam initalized successfully")
is_initalized = true
func get_player_avatar(steam_id: int) -> ImageTexture:
Steam.getPlayerAvatar(Steam.AVATAR_LARGE, steam_id)
var result = await Steam.avatar_loaded # returns (avatar_id, width, avatar_data)
while result[0] != steam_id:
result = await Steam.avatar_loaded
var width: int = result[1]
var avatar_data: PackedByteArray = result[2]
var image := Image.create_from_data(width, width, false, Image.FORMAT_RGBA8, avatar_data)
if width > 128:
image.resize(128, 128, Image.INTERPOLATE_LANCZOS)
return ImageTexture.create_from_image(image)

View File

@@ -0,0 +1 @@
uid://6im158hn15uv

View File

@@ -0,0 +1,58 @@
class_name PlayerInfoResource
extends Resource
var peer_id: int = 0
var username: String = "None"
var avatar: ImageTexture
var avatar_modulated_color: Color
var is_steam: bool = false
var steam_id: int = 0
func init_enet(peer_id: int, username: String, avatar_bytes: PackedByteArray):
is_steam = false
self.peer_id = peer_id
self.username = username
var avatar_image := Image.new()
var err := avatar_image.load_png_from_buffer(avatar_bytes)
if err != 0:
push_error("Could not load avatar image for peer: %s, Error: %s" % [peer_id, err])
return
avatar_image.resize(100, 100, Image.INTERPOLATE_LANCZOS)
self.avatar = ImageTexture.create_from_image(avatar_image)
self.avatar_modulated_color = get_modulated_avatar_color(avatar)
func init_steam(peer_id: int, username: String, avatar: ImageTexture, steam_id: int):
is_steam = true
self.peer_id = peer_id
self.username = username
self.avatar = avatar
self.avatar_modulated_color = get_modulated_avatar_color(avatar)
self.steam_id = steam_id
func to_str() -> String:
var fmt_string := "Peer ID: %s\nUsername: %s\nIs Steam?: %s\nSteam ID: %s"
var final_string := fmt_string % [peer_id, username, is_steam, steam_id]
return final_string
func get_modulated_avatar_color(avatar: ImageTexture) -> Color:
var avatar_image: Image = avatar.get_image()
if avatar_image.get_width() > 128:
avatar_image.resize(128, 128, Image.INTERPOLATE_LANCZOS)
var new_avatar_texture = ImageTexture.create_from_image(avatar_image)
# modulate steam profile picture to use for username color in chat
var avatar_modulated_color := Vector3.ZERO
var texture_size := avatar.get_size()
var image := avatar.get_image()
for y in range(0, texture_size.y):
for x in range(0, texture_size.x):
var pixel := image.get_pixel(x, y)
avatar_modulated_color += Vector3(pixel.r, pixel.g, pixel.b)
avatar_modulated_color /= texture_size.x * texture_size.y
print(Color(avatar_modulated_color.x, avatar_modulated_color.y, avatar_modulated_color.z))
return Color(avatar_modulated_color.x, avatar_modulated_color.y, avatar_modulated_color.z)

View File

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