diff --git a/src/CommandHandlers/CounterHandler.cs b/src/CommandHandlers/CounterHandler.cs new file mode 100644 index 0000000..e1c4291 --- /dev/null +++ b/src/CommandHandlers/CounterHandler.cs @@ -0,0 +1,27 @@ +using sodoffmmo.Attributes; +using sodoffmmo.Core; +using sodoffmmo.Data; + +namespace sodoffmmo.CommandHandlers; + +[ExtensionCommandHandler("SCE")] +class CounterEventHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"SCE","p":{"NAME":"COUNT"},"r":-1}} + if (client.Room?.HasAmbassador() is bool b && b) { + string name = receivedObject.Get("p").Get("NAME"); + if (name == "COUNT" || name == "COUNT2" || name == "COUNT3") { + int index = name switch { + "COUNT" => 0, + "COUNT2" => 1, + "COUNT3" => 2 + }; + client.Room.ambassadorGauges[index] = Math.Min(100, client.Room.ambassadorGauges[index]+(1/Configuration.ServerConfiguration.AmbassadorGaugePlayers)); + client.Room.Send(Utils.VlNetworkPacket(client.Room.AddAmbassadorData(new()), client.Room.Id)); + } else { + Console.WriteLine("Invalid attempt to increment room var "+name+"."); + } + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/Core/Configuration.cs b/src/Core/Configuration.cs index 727e7dd..f8b2687 100644 --- a/src/Core/Configuration.cs +++ b/src/Core/Configuration.cs @@ -33,6 +33,11 @@ internal sealed class ServerConfiguration { public int EventTimer { get; set; } = 30; public int FirstEventTimer { get; set; } = 10; public Dictionary RoomAlerts { get; set; } = new(); + public string[] AmbassadorRooms { get; set; } = Array.Empty(); + public int AmbassadorGaugeStart { get; set; } = 75; + public float AmbassadorGaugeDecayRate { get; set; } = 60; + public bool AmbassadorGaugeDecayOnlyWhenInRoom { get; set; } = true; + public float AmbassadorGaugePlayers { get; set; } = 0.5f; public int RacingMaxPlayers { get; set; } = 6; public int RacingMinPlayers { get; set; } = 2; public int RacingMainLobbyTimer { get; set; } = 15; diff --git a/src/Core/Room.cs b/src/Core/Room.cs index 31f7b7a..0300813 100644 --- a/src/Core/Room.cs +++ b/src/Core/Room.cs @@ -111,7 +111,7 @@ public class Room { roomInfo.Add(false); // is password protected roomInfo.Add((short)clients.Count); // player count roomInfo.Add((short)4096); // max player count - roomInfo.Add(RoomVariables); // variables + roomInfo.Add(AddAmbassadorData(RoomVariables)); // variables roomInfo.Add((short)0); // spectator count roomInfo.Add((short)0); // max spectator count @@ -143,7 +143,7 @@ public class Room { r1.Add(false); r1.Add((short)clients.Count); // player count r1.Add((short)4096); // max player count - r1.Add(new NetworkArray()); + r1.Add(AddAmbassadorData(new())); r1.Add((short)0); r1.Add((short)0); @@ -154,6 +154,35 @@ public class Room { return NetworkObject.WrapObject(0, 15, obj).Serialize(); } + public double[] ambassadorGauges; + System.Timers.Timer? ambassadorTimer; + + public bool HasAmbassador() { + return ambassadorTimer != null; + } + + public void InitAmbassador() { + ambassadorGauges = new double[3]; // There is always a maximum of 3. + for (int i=0;i<3;i++) ambassadorGauges[i] = Configuration.ServerConfiguration.AmbassadorGaugeStart; + ambassadorTimer = new System.Timers.Timer(Configuration.ServerConfiguration.AmbassadorGaugeDecayRate*1000); + ambassadorTimer.AutoReset = true; + ambassadorTimer.Enabled = true; + ambassadorTimer.Elapsed += (sender, e) => { + if (!Configuration.ServerConfiguration.AmbassadorGaugeDecayOnlyWhenInRoom || clients.Count > 0) { + for (int i=0;i<3;i++) ambassadorGauges[i] = Math.Max(0, ambassadorGauges[i]-1); + Send(Utils.VlNetworkPacket(AddAmbassadorData(new()), Id)); + } + }; + } + + internal NetworkArray AddAmbassadorData(NetworkArray array) { + if (HasAmbassador()) { // If this isn't null that means ambassadors are initialized. + array.Add(NetworkArray.VlElement("COUNT", (int)Math.Round(ambassadorGauges[0]), isPersistent: true)); + array.Add(NetworkArray.VlElement("COUNT2", (int)Math.Round(ambassadorGauges[1]), isPersistent: true)); + array.Add(NetworkArray.VlElement("COUNT3", (int)Math.Round(ambassadorGauges[2]), isPersistent: true)); + } + return array; + } private int alertId = -1; private Random random = new Random(); @@ -166,6 +195,8 @@ public class Room { } public void SendAllAlerts(Client client) { + return; // Disables joining ongoing alerts (since it doesn't work properly). + foreach (AlertInfo alert in alerts) { if (alert.IsRunning()) StartAlert(alert, client); } @@ -173,8 +204,6 @@ public class Room { private void StartAlert(AlertInfo alert, Client? specificClient = null) { - if (specificClient != null) return; // Disables joining ongoing alerts. - NetworkArray NewRoomVariables = new(); NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_START, alertId++, isPersistent: true)); NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_TYPE, alert.type, isPersistent: true)); diff --git a/src/Server.cs b/src/Server.cs index 1340baa..c9cc828 100644 --- a/src/Server.cs +++ b/src/Server.cs @@ -31,16 +31,22 @@ public class Server { foreach (var room in Configuration.ServerConfiguration.RoomAlerts) { foreach (var alert in room.Value) { - Console.WriteLine($"Setup alert \"{alert[0]}\" for {room.Key}"); - Room.GetOrAdd(room.Key).AddAlert(new Room.AlertInfo( + Room.AlertInfo alertInfo = new Room.AlertInfo( alert[0], // type float.Parse(alert[1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat), // duration Int32.Parse(alert[2]), Int32.Parse(alert[3]), // start min - max for random start time Int32.Parse(alert[4]), Int32.Parse(alert[5]) // extra parameters for specific alarm types - )); + ); + Console.WriteLine($"Setup alert {alertInfo} for {room.Key}"); + Room.GetOrAdd(room.Key).AddAlert(alertInfo); } } + foreach (var room in Configuration.ServerConfiguration.AmbassadorRooms) { + Console.WriteLine($"Setup Ambassador for {room}"); + Room.GetOrAdd(room).InitAmbassador(); + } + await Listen(listener); } diff --git a/src/appsettings.json b/src/appsettings.json index b4b10bf..464abcc 100644 --- a/src/appsettings.json +++ b/src/appsettings.json @@ -30,6 +30,21 @@ "ClubSSInt" : [ ["3", 20.0, 30, 240, 0, 16] ], }, + "// AmbassadorRooms": "Rooms with ambassadors (MB funzones).", + "AmbassadorRooms": ["Spaceport"], + + "// AmbassadorGaugeStart": "The starting value for all ambassador gauges (MB funzones).", + "AmbassadorGaugeStart": 75, + + "// AmbassadorGaugeDecayRate": "Time in seconds before ambassador gauges decrease (MB funzones).", + "AmbassadorGaugeDecayRate": 60, + + "// AmbassadorGaugeDecayOnlyWhenInRoom": "Only decrease ambassador gauges when there is at least one player in the room (MB funzones).", + "AmbassadorGaugeDecayOnlyWhenInRoom": true, + + "// AmbassadorGaugePlayers": "Denominator for filling the ambassador gauges (MB funzones).", + "AmbassadorGaugePlayers": 0.5, + "// RacingMaxPlayers": "maximum players allowed in Thunder Run Racing (no more than 6)", "RacingMaxPlayers": 6,