using sodoffmmo.Data; using System; using System.Collections.Generic; using System.Numerics; using System.Text; namespace sodoffmmo.Core { public class SWRacingRoom : Room { class SWPlayerState { public int Index; public Vector3 PosTransform = new(); public string Token = ""; public bool IsHost; public bool IsReady; public bool SceneLoaded; public bool CountdownFinished; public int ColorIndex; public string VehicleResName = ""; public int CurrentLap; public float FinishedTime = -1f; public bool IsTrackPrebuilt; public int TrackIdx; public string TrackStatus = "ZR"; } public SWRacingRoom() : base(null, "ShipWreckMPRoom", true) { } public bool CountdownStarted { get; set; } = false; public bool RaceOngoing { get; set; } = false; public bool BuddiesOnly { get; set; } = false; Dictionary Players = new(); Client? host = null; int nextIndex = 1; public void AddPlayer(Client client) { lock (roomLock) { var state = new SWPlayerState { Index = nextIndex++ }; if(host is null) { host = client; state.IsHost = true; } Players[client] = state; } } public int GetIndex(Client client) { lock (roomLock) { var state = Players[client]; return state.Index; } } public int GetReadyCount() { lock (roomLock) { int readyCount = 0; foreach(var (client, s) in Players) { if (s.IsReady) readyCount++; } return readyCount; } } public IEnumerable GetPlayersWithinRadius(Vector3 blast, float hitRadius, Client? excluding) { lock (roomLock) { float targetRadiusSquared = hitRadius * hitRadius; List targetedPlayers = []; foreach(var player in Players) { if (player.Key.ClientID == excluding?.ClientID) continue; if (Vector3.DistanceSquared(player.Value.PosTransform, blast) < targetRadiusSquared) targetedPlayers.Add(player.Value.Index); } return targetedPlayers; } } public void SetPlayerPosition(Client client, float X, float Y, float Z) { lock (roomLock) { var state = Players[client]; state.PosTransform.X = X; state.PosTransform.Y = Y; state.PosTransform.Z = Z; } } public void SetReady(Client client, bool ready) { lock (roomLock) { var state = Players[client]; state.IsReady = ready; } } public void SetTrack(Client client, int trackId) { lock (roomLock) { var state = Players[client]; state.TrackIdx = trackId; } } public void SetTrackStatus(Client client, string statusCode) { lock (roomLock) { var state = Players[client]; state.TrackStatus = statusCode; } } public void SetIsPrebuiltTrack(Client client, bool isPrebuiltTrack) { lock (roomLock) { var state = Players[client]; state.IsTrackPrebuilt = isPrebuiltTrack; } } public void SetBoat(Client client, string boatRes, int colorIndex = 0) { lock (roomLock) { var state = Players[client]; state.VehicleResName = boatRes; state.ColorIndex = colorIndex; } } public void SetToken(Client client, string token) { lock (roomLock) { var state = Players[client]; state.Token = token; } } public bool SetSceneLoaded(Client client) { lock (roomLock) { Players[client].SceneLoaded = true; foreach (var (_, s) in Players) if (!s.SceneLoaded) return false; return true; } } public bool SetCountdownFinished(Client client) { lock (roomLock) { Players[client].CountdownFinished = true; foreach (var (_, s) in Players) if (!s.CountdownFinished) return false; return true; } } public void SetPlayerLap(Client client, int lap) { lock (roomLock) { var state = Players[client]; state.CurrentLap = lap; } } public void SetFinishedTime(Client client, float time) { lock (roomLock) { var state = Players[client]; state.FinishedTime = time; } } public NetworkPacket GetAMPacket() { List info = [ "AM" ]; foreach(var (client, s) in Players) { info.Add(s.IsHost ? "ZJ" : ""); info.Add(client.PlayerData.UNToken); info.Add(s.Index.ToString()); info.Add(s.ColorIndex.ToString()); info.Add(s.VehicleResName); info.Add(s.IsReady ? "AN" : ""); info.Add(s.IsTrackPrebuilt ? "ZP" : "ZQ"); info.Add(s.TrackIdx.ToString()); info.Add(s.TrackStatus); } string joined = string.Join("|", info); return Utils.ArrNetworkPacket(["AM", joined], "", Id); } System.Timers.Timer? countdownTimer; int lobbyCounter; public void TryStartLobbyCountdown() { Console.WriteLine($"Attempted To Start SWL Lobby Countdown On SWL {Id}. Player Count - {Players.Count}"); lock (roomLock) { if (Players.Count <= 1) return; // this is multiplayers, don't just start a singleplayer time trial lmao if (CountdownStarted || GetReadyCount() < Players.Count) return; string joined = string.Join("|", "AB", Players.Count.ToString(), "3"); Send(Utils.ArrNetworkPacket([joined], "", Id)); CountdownStarted = true; Console.WriteLine($"Countdown Started On SWL {Id}"); } lobbyCounter = 3; countdownTimer = new(1000) { AutoReset = true }; countdownTimer.Elapsed += TickLobbyCountdown; countdownTimer.Enabled = true; } private void TickLobbyCountdown(object? sender, System.Timers.ElapsedEventArgs e) { Console.WriteLine($"Lobby Countdown Tick TS - {DateTime.Now}"); if(--lobbyCounter <= 0) { countdownTimer!.Stop(); string joined = string.Join("|", "ZH", lobbyCounter.ToString()); Send(Utils.ArrNetworkPacket([joined], "", Id)); RaceOngoing = true; } } } }