Add direct-connect multiplayer foundation
This commit is contained in:
parent
9e9850dd20
commit
24f8263175
36 changed files with 2633 additions and 45 deletions
96
network/player_spawn_service.gd
Normal file
96
network/player_spawn_service.gd
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
class_name PlayerSpawnService
|
||||
extends Node
|
||||
|
||||
const PlayerScene: PackedScene = preload("res://player/player.tscn")
|
||||
|
||||
signal avatar_spawned(peer_id: int, avatar: Player)
|
||||
signal avatar_removed(peer_id: int)
|
||||
|
||||
var _players_root: Node3D
|
||||
var _local_player: Player
|
||||
var _spawn_transform: Transform3D
|
||||
var _avatars: Dictionary[int, Player] = {}
|
||||
var _local_peer_id: int = 1
|
||||
|
||||
|
||||
func setup(
|
||||
players_root: Node3D,
|
||||
local_player: Player,
|
||||
spawn_transform: Transform3D,
|
||||
) -> void:
|
||||
_players_root = players_root
|
||||
_local_player = local_player
|
||||
_spawn_transform = spawn_transform
|
||||
|
||||
|
||||
func register_local_player(peer_id: int) -> void:
|
||||
if _local_player == null:
|
||||
return
|
||||
for existing_id: int in _avatars.keys():
|
||||
if _avatars[existing_id] == _local_player:
|
||||
_avatars.erase(existing_id)
|
||||
_local_peer_id = peer_id
|
||||
_avatars[peer_id] = _local_player
|
||||
_local_player.name = "Player_%d" % peer_id
|
||||
_local_player.set_local_control(true)
|
||||
_local_player.set_network_peer_id(peer_id)
|
||||
|
||||
|
||||
func spawn_remote_player(
|
||||
peer_id: int,
|
||||
transform: Transform3D,
|
||||
authoritative_simulation: bool = false,
|
||||
) -> Player:
|
||||
if peer_id <= 0 or peer_id == _local_peer_id:
|
||||
return null
|
||||
var existing: Player = _avatars.get(peer_id)
|
||||
if existing != null and is_instance_valid(existing):
|
||||
return existing
|
||||
var avatar := PlayerScene.instantiate() as Player
|
||||
avatar.name = "Player_%d" % peer_id
|
||||
avatar.set_local_control(false)
|
||||
avatar.set_network_peer_id(peer_id)
|
||||
_players_root.add_child(avatar)
|
||||
avatar.global_transform = transform
|
||||
avatar.configure_network_remote(authoritative_simulation)
|
||||
_avatars[peer_id] = avatar
|
||||
avatar_spawned.emit(peer_id, avatar)
|
||||
return avatar
|
||||
|
||||
|
||||
func remove_peer(peer_id: int) -> void:
|
||||
if peer_id == _local_peer_id:
|
||||
return
|
||||
var avatar: Player = _avatars.get(peer_id)
|
||||
_avatars.erase(peer_id)
|
||||
if avatar != null and is_instance_valid(avatar):
|
||||
avatar.queue_free()
|
||||
avatar_removed.emit(peer_id)
|
||||
|
||||
|
||||
func clear_remote_players() -> void:
|
||||
for peer_id: int in _avatars.keys():
|
||||
if peer_id != _local_peer_id:
|
||||
remove_peer(peer_id)
|
||||
|
||||
|
||||
func get_avatar(peer_id: int) -> Player:
|
||||
return _avatars.get(peer_id)
|
||||
|
||||
|
||||
func get_peer_ids() -> Array[int]:
|
||||
var result: Array[int] = []
|
||||
for peer_id: int in _avatars:
|
||||
result.append(peer_id)
|
||||
result.sort()
|
||||
return result
|
||||
|
||||
|
||||
func get_spawn_transform_for_index(index: int) -> Transform3D:
|
||||
if index <= 0:
|
||||
return _spawn_transform
|
||||
var angle: float = float(index) * 2.3999632297
|
||||
var ring: float = 1.4 + floor(float(index - 1) / 8.0) * 1.2
|
||||
var result: Transform3D = _spawn_transform
|
||||
result.origin += Vector3(cos(angle) * ring, 0.0, sin(angle) * ring)
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue