97 lines
2.5 KiB
GDScript3
97 lines
2.5 KiB
GDScript3
|
|
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
|