components/game.cs

Game component that manages player roles and round lifecycle for a hide-and-seek style game. It tracks players, finds spawnpoints from the selected map, assigns one random seeker and the rest hiders at round start, spawns/destroys role entities and ragdolls/spectators, and handles simple lobby/start logic.

NetworkingFile Access
using Sandbox;
using Sandbox.Network;
using System.Collections.Generic;
using System;
using Sandbox.Platform;

public class game : Component, Component.INetworkListener
{
	[Property] public GameObject Hider {get;set;}
	[Property] public GameObject Seeker {get;set;}
	[Property] public GameObject Spectator {get;set;}
	[Property] public MapInstance Map {get;set;}
	
	List<GameObject> Hiders = new();
	List<GameObject> Seekers = new();
	List<Connection> Players = new();
	List<GameObject> Ragdolls = new();
	List<GameObject> Spectators = new();
	
	[Sync] public bool IsActive {get;set;}
	Random random = new(); TimeUntil Grace;
	[Sync] public TimeUntil Time {get;set;}
	
	protected override void OnUpdate()
	{ if (!Networking.IsHost) return;
		Players = new(Connection.All);
		for (int i = Players.Count - 1; i >= 0; i--)
			if (!Players[i].IsActive)
				Players.RemoveAt(i);
		
		Hiders = new(Scene.FindAllWithTag("hider"));
		Seekers = new(Scene.FindAllWithTag("seeker"));
		Ragdolls = new(Scene.FindAllWithTag("ragdoll"));
		Spectators = new(Scene.FindAllWithTag("spectator"));
		
		if (Players.Count >= 2 && !IsActive && Grace)
		{ IsActive = true; Grace = 1f; Time = 180f;
			var Spawnpoints = new List<GameObject>(Map.GameObject.Children);
			for (int i = Spawnpoints.Count - 1; i >= 0; i--)
				if (Spawnpoints[i].Name != "info_player_start")
					Spawnpoints.RemoveAt(i);
			
			var seeker = Players[random.Next(Players.Count)];
			var Seeker_Spawnpoint = Spawnpoints[random.Next(Spawnpoints.Count)];
			
			foreach (var Player in Players)
			{
				if (Player == seeker)
				{
					var skr = Seeker.Clone(Seeker_Spawnpoint.WorldPosition);
					skr.NetworkSpawn(Player); Spawnpoints.Remove(Seeker_Spawnpoint);
				continue; }
				
				var hider = Hider.Clone(Spawnpoints[random.Next(Spawnpoints.Count)].WorldPosition);
				hider.NetworkSpawn(Player);
			}
			
			foreach (var Ragdoll in Ragdolls) Ragdoll.Destroy();
			foreach (var spectator in Spectators) spectator.Destroy();
		}
		
		if ((Hiders.Count <= 0 || Seekers.Count <= 0 || Time) && IsActive && Grace)
		{ IsActive = false; Grace = 1f; Time = 180f;
			foreach (var hider in Hiders) hider.Destroy();
			foreach (var seeker in Seekers) seeker.Destroy();
			foreach (var Ragdoll in Ragdolls) Ragdoll.Destroy();
			foreach (var spectator in Spectators) spectator.Destroy();
		}
	}
	
	public void OnActive(Connection connection)
	{
		if (!IsActive && Players.Count < 2)
		{
			var _ = Spectator.Clone();
			_.NetworkSpawn(connection);
		}
	}
	
	protected override async void OnStart() {
		Networking.CreateLobby(new LobbyConfig());
		Map.MapName = _game.CurrentlySelectedMap;
		
		while (LoadingScreen.IsVisible)
			await Task.Delay(100);
		Chat.AddText("You need at least 2 players.");
	}
}