freeftf/global/multiplayer.gd

122 lines
3.3 KiB
GDScript3
Raw Normal View History

2025-07-18 19:32:37 +01:00
class_name MultiplayerClass
extends Node
const ADDRESS: String = "127.0.0.1"
const PORT: int = 4516
var peer: ENetMultiplayerPeer = null
2025-07-31 13:57:50 +02:00
var players: Array[Dictionary] = []
var fuseboxes: int = 0
var playerlist_label: Label = null
2025-07-18 19:32:37 +01:00
## Host Specific
# Hosts server
func host_server() -> void:
peer = ENetMultiplayerPeer.new()
if peer.create_server(PORT) != OK:
peer = null
return
multiplayer.multiplayer_peer = peer
if multiplayer.peer_connected.connect(_on_player_joined) != OK:
print("Failed to connect signal")
if multiplayer.peer_disconnected.connect(_on_player_left) != OK:
print("Failed to connect signal")
_on_player_joined(multiplayer.get_unique_id())
# Runs when player joins
func _on_player_joined(id: int) -> void:
players.push_back({
"id": id,
"loaded": false,
"hunter": false,
2025-07-31 13:57:50 +02:00
"captured": false,
"escaped": false,
2025-07-18 19:32:37 +01:00
})
2025-07-31 13:57:50 +02:00
send_playerlist()
2025-07-18 19:32:37 +01:00
# Runs when player leaves
func _on_player_left(id: int) -> void:
players = players.filter(func (player: Dictionary) -> bool: return player.id != id)
2025-07-31 13:57:50 +02:00
send_playerlist()
# Prepares the label text for the playerlist on the join/host screen
func send_playerlist() -> void:
var playerlist: String = ""
for player: Dictionary in players:
playerlist += str(player.id)
playerlist += "\n"
update_playerlist.rpc(playerlist)
2025-07-18 19:32:37 +01:00
# Switches the scene, and waits until everyone is fully loaded.
@rpc("authority", "call_local", "reliable")
func switch_scene(path: String) -> void:
2025-07-31 13:57:50 +02:00
playerlist_label = null
2025-07-18 19:32:37 +01:00
if multiplayer.is_server():
_scene_loaded.rpc_id(1)
while true:
var loaded: bool = true
for player: Dictionary in players:
if player.loaded == false:
loaded = false
break
if loaded:
break
await get_tree().create_timer(0.1).timeout
if get_tree().change_scene_to_file(path) != OK:
print("Failed to change to scene.")
else:
if get_tree().change_scene_to_file(path) != OK:
print("Failed to change to scene.")
_scene_loaded.rpc_id(1)
# Callback to switch_scene from the remote peer
@rpc("any_peer", "call_local", "reliable")
func _scene_loaded() -> void:
var id: int = multiplayer.get_remote_sender_id()
if multiplayer.is_server():
for i: int in range(players.size()):
if players[i].id == multiplayer.get_remote_sender_id():
players[i].loaded = true
2025-07-31 13:57:50 +02:00
func _process(_delta: float) -> void:
if multiplayer.multiplayer_peer and multiplayer.is_server() and !players.is_empty():
var lost: bool = true
for player: Dictionary in players:
if (!player.captured or !player.escaped) and !player.hunter:
lost = false
if lost:
terminate_multiplayer.rpc()
2025-07-18 19:32:37 +01:00
## Client Specific
# Joins a server
func join_server() -> void:
peer = ENetMultiplayerPeer.new()
if peer.create_client(ADDRESS, PORT) != OK:
peer = null
return
multiplayer.multiplayer_peer = peer
## Shared
# Terminates all Multiplayer functionality.
2025-07-31 13:57:50 +02:00
@rpc("authority", "call_local", "reliable")
2025-07-18 19:32:37 +01:00
func terminate_multiplayer() -> void:
multiplayer.multiplayer_peer = null
2025-07-31 13:57:50 +02:00
players = []
fuseboxes = 0
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if get_tree().change_scene_to_file("res://ui/main_menu.tscn") != OK:
print("Failed to change to scene.")
# Updates the player list
@rpc("authority", "call_local", "reliable")
func update_playerlist(list: String) -> void:
if playerlist_label != null:
playerlist_label.text = list