114 lines
2.8 KiB
C#
114 lines
2.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Creates a networked game lobby and assigns player prefabs to connected clients.
|
|
/// </summary>
|
|
[Title( "Network Manager" )]
|
|
[Category( "Networking" )]
|
|
[Icon( "electrical_services" )]
|
|
public sealed class NetworkManager : Component, Component.INetworkListener
|
|
{
|
|
/// <summary>
|
|
/// Create a server (if we're not joining one)
|
|
/// </summary>
|
|
[Property]
|
|
public bool StartServer { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// The prefab to spawn for the player to control.
|
|
/// </summary>
|
|
[Property]
|
|
public GameObject PlayerPrefab { get; set; }
|
|
|
|
/// <summary>
|
|
/// A list of points to choose from randomly to spawn the player in. If not set, we'll spawn at the
|
|
/// location of the NetworkHelper object.
|
|
/// </summary>
|
|
[Property]
|
|
public List<GameObject> SpawnPoints { get; set; }
|
|
|
|
protected override async Task OnLoad()
|
|
{
|
|
if ( Scene.IsEditor )
|
|
return;
|
|
|
|
if ( StartServer && !Networking.IsActive )
|
|
{
|
|
LoadingScreen.Title = "Creating Lobby";
|
|
await Task.DelayRealtimeSeconds( 0.1f );
|
|
Networking.CreateLobby( new() );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A client is fully connected to the server. This is called on the host.
|
|
/// </summary>
|
|
public void OnActive( Connection channel )
|
|
{
|
|
Log.Info( $"Player '{channel.DisplayName}' has joined the game" );
|
|
|
|
if ( !PlayerPrefab.IsValid() )
|
|
return;
|
|
|
|
//
|
|
// Find a spawn location for this player
|
|
//
|
|
var startLocation = FindSpawnLocation().WithScale( 1 );
|
|
|
|
// Spawn this object and make the client the owner
|
|
var player = PlayerPrefab.Clone( startLocation, name: $"Player - {channel.DisplayName}" );
|
|
player.NetworkSpawn( channel );
|
|
|
|
var dedugan = player.Components.Get<Dedugan>( true );
|
|
|
|
dedugan.SetupConnection( channel );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a client disconnects from the server.
|
|
/// </summary>
|
|
public void OnDisconnected( Connection channel )
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the connection is being torn down.
|
|
/// </summary>
|
|
public void OnBecomeInactive( Connection channel )
|
|
{
|
|
// Optional: Handle any cleanup before player becomes fully inactive
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find the most appropriate place to respawn
|
|
/// </summary>
|
|
Transform FindSpawnLocation()
|
|
{
|
|
//
|
|
// If they have spawn point set then use those
|
|
//
|
|
if ( SpawnPoints is not null && SpawnPoints.Count > 0 )
|
|
{
|
|
return Random.Shared.FromList( SpawnPoints, default ).WorldTransform;
|
|
}
|
|
|
|
//
|
|
// If we have any SpawnPoint components in the scene, then use those
|
|
//
|
|
var spawnPoints = Scene.GetAllComponents<SpawnPoint>().ToArray();
|
|
if ( spawnPoints.Length > 0 )
|
|
{
|
|
return Random.Shared.FromArray( spawnPoints ).WorldTransform;
|
|
}
|
|
|
|
//
|
|
// Failing that, spawn where we are
|
|
//
|
|
return WorldTransform;
|
|
}
|
|
}
|