forked from SoDOff-Project/sodoff-mmo
Added support for Red Alert and Disco Alert (#3)
Revamped entire room Alerts system. Merged RoomWithAlert into Room (as part of the revamp). This added support for Red Alert and Disco Alert. This meant that I had to revamp the room alerts system to allow for multiple alerts per room. Events hopefully shouldn't overlap each other in the same room. An extra feature is that an alert will start for a player that has just entered the room (with a duration reduced based on when the alert initially started). I shoved this functionality's working into SetUserVariablesHandler on line 30. This feature doesn't seem to work when leaving a non-MMO rooms such as minigames (may be related to missed JL command).
This commit is contained in:
parent
518c01c43f
commit
65eeb7dd53
@ -27,6 +27,7 @@ class SetUserVariablesHandler : CommandHandler {
|
|||||||
client.PlayerData.InitFromNetworkData(suvData);
|
client.PlayerData.InitFromNetworkData(suvData);
|
||||||
UpdatePlayersInRoom();
|
UpdatePlayersInRoom();
|
||||||
SendSUVToPlayerInRoom();
|
SendSUVToPlayerInRoom();
|
||||||
|
client.Room.SendAllAlerts(client);
|
||||||
} else {
|
} else {
|
||||||
UpdateVars();
|
UpdateVars();
|
||||||
}
|
}
|
||||||
|
133
src/Core/Room.cs
133
src/Core/Room.cs
@ -153,4 +153,137 @@ public class Room {
|
|||||||
obj.Add("g", Group);
|
obj.Add("g", Group);
|
||||||
return NetworkObject.WrapObject(0, 15, obj).Serialize();
|
return NetworkObject.WrapObject(0, 15, obj).Serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int alertId = -1;
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
List<AlertInfo> alerts = new();
|
||||||
|
|
||||||
|
public void AddAlert(AlertInfo alert) {
|
||||||
|
alerts.Add(alert);
|
||||||
|
ResetAlertTimer(alert);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendAllAlerts(Client client) {
|
||||||
|
foreach (AlertInfo alert in alerts) {
|
||||||
|
if (alert.IsRunning()) StartAlert(alert, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void StartAlert(AlertInfo alert, Client? specificClient = null) {
|
||||||
|
alert.songId = random.Next(0, alert.songs);
|
||||||
|
NetworkArray NewRoomVariables = new();
|
||||||
|
NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_START, alertId++, isPersistent: true));
|
||||||
|
NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_TYPE, alert.type, isPersistent: true));
|
||||||
|
double duration = (alert.endTime - DateTime.Now).TotalSeconds;
|
||||||
|
NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_LENGTH, alert.type == "1" ? alert.redAlertDuration : duration, isPersistent: true));
|
||||||
|
if (alert.type == "1") NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_TIMEOUT, duration, isPersistent: true));
|
||||||
|
if (alert.type == "3") NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_SONG, (double)alert.songId, isPersistent: true));
|
||||||
|
NetworkPacket packet = Utils.VlNetworkPacket(NewRoomVariables, Id);
|
||||||
|
if (specificClient is null) {
|
||||||
|
RoomVariables = NewRoomVariables;
|
||||||
|
Send(packet);
|
||||||
|
Console.WriteLine("Started event " +alert + " in room " + Name);
|
||||||
|
} else {
|
||||||
|
specificClient.Send(packet);
|
||||||
|
Console.WriteLine("Added " + specificClient.PlayerData.DiplayName + " to event " + alert + " with " + duration + " seconds remaining");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetAlertTimer(AlertInfo alert) {
|
||||||
|
System.Timers.Timer? timer = alert.timer;
|
||||||
|
if (timer != null) {
|
||||||
|
timer.Stop();
|
||||||
|
timer.Close();
|
||||||
|
}
|
||||||
|
DateTime startTime = DateTime.Now.AddMilliseconds(random.Next(alert.minTime * 1000, alert.maxTime * 1000));
|
||||||
|
DateTime endTime = startTime.AddSeconds(alert.duration);
|
||||||
|
for (int i = 0; i < alerts.IndexOf(alert); i++) {
|
||||||
|
// Prevent overlap between two events.
|
||||||
|
if (alerts[i].Overlaps(endTime)) {
|
||||||
|
startTime = alerts[i].endTime.AddSeconds(5);
|
||||||
|
endTime = startTime.AddSeconds(alert.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timer = new System.Timers.Timer((startTime - DateTime.Now).TotalMilliseconds);
|
||||||
|
timer.AutoReset = false;
|
||||||
|
timer.Enabled = true;
|
||||||
|
timer.Elapsed += (sender, e) => StartAlert(alert);
|
||||||
|
timer.Elapsed += (sender, e) => ResetAlertTimer(alert);
|
||||||
|
alert.timer = timer;
|
||||||
|
Console.WriteLine("Event " + alert + " in " + Name + " scheduled for " + startTime.ToString("MM/dd/yyyy HH:mm:ss tt") + " (in " + (startTime - DateTime.Now).TotalSeconds + " seconds)");
|
||||||
|
alert.startTime = startTime;
|
||||||
|
alert.endTime = endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string REDALERT_START = "RA_S";
|
||||||
|
private const string REDALERT_TYPE = "RA_A";
|
||||||
|
private const string REDALERT_LENGTH = "RA_L";
|
||||||
|
private const string REDALERT_TIMEOUT = "RA_T";
|
||||||
|
private const string REDALERT_SONG = "RA_SO";
|
||||||
|
|
||||||
|
public class AlertInfo {
|
||||||
|
public readonly string type;
|
||||||
|
public readonly double duration;
|
||||||
|
public readonly int minTime;
|
||||||
|
public readonly int maxTime;
|
||||||
|
public readonly int redAlertDuration;
|
||||||
|
public readonly int songs;
|
||||||
|
public int songId;
|
||||||
|
|
||||||
|
public DateTime startTime {
|
||||||
|
get {
|
||||||
|
return newStartTime;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
oldStartTime = newStartTime;
|
||||||
|
newStartTime = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime endTime {
|
||||||
|
get {
|
||||||
|
return newEndTime;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
oldEndTime = newEndTime;
|
||||||
|
newEndTime = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime newStartTime;
|
||||||
|
private DateTime newEndTime;
|
||||||
|
private DateTime oldStartTime;
|
||||||
|
private DateTime oldEndTime;
|
||||||
|
|
||||||
|
public System.Timers.Timer? timer = null;
|
||||||
|
|
||||||
|
public AlertInfo(string type, double duration = 20.0, int minTime = 30, int maxTime = 240, int redAlertDuration = 60, int songs = 16) {
|
||||||
|
this.type = type;
|
||||||
|
this.duration = duration;
|
||||||
|
this.minTime = minTime;
|
||||||
|
this.maxTime = maxTime;
|
||||||
|
this.redAlertDuration = redAlertDuration;
|
||||||
|
this.songs = songs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overlaps(DateTime time) {
|
||||||
|
return (time >= oldStartTime && time <= oldEndTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRunning() {
|
||||||
|
return Overlaps(DateTime.Now);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return type switch {
|
||||||
|
"1" => "RedAlert",
|
||||||
|
"2" => "DiscoAlert",
|
||||||
|
"3" => "DanceOff",
|
||||||
|
_ => type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
using sodoffmmo.Data;
|
|
||||||
using System.Timers;
|
|
||||||
|
|
||||||
namespace sodoffmmo.Core;
|
|
||||||
class RoomWithAlert : Room {
|
|
||||||
private int alertId;
|
|
||||||
private System.Timers.Timer? timer = null;
|
|
||||||
private Random random = new Random();
|
|
||||||
|
|
||||||
private int minTime;
|
|
||||||
private int maxTime;
|
|
||||||
private int songs;
|
|
||||||
|
|
||||||
public RoomWithAlert(string name, int minTime = 30, int maxTime = 240, int songs = 16) : base (name) {
|
|
||||||
alertId = -1;
|
|
||||||
|
|
||||||
this.minTime = minTime;
|
|
||||||
this.maxTime = maxTime;
|
|
||||||
this.songs = songs;
|
|
||||||
|
|
||||||
SetTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartAlert(Object? source, ElapsedEventArgs e) {
|
|
||||||
int songId = random.Next(0, songs);
|
|
||||||
RoomVariables = new();
|
|
||||||
RoomVariables.Add(NetworkArray.VlElement("RA_S", ++alertId, isPersistent: true));
|
|
||||||
RoomVariables.Add(NetworkArray.VlElement("RA_A", "3", isPersistent: true));
|
|
||||||
RoomVariables.Add(NetworkArray.VlElement("RA_L", 20.0, isPersistent: true));
|
|
||||||
RoomVariables.Add(NetworkArray.VlElement("RA_SO", (double)songId, isPersistent: true));
|
|
||||||
NetworkPacket packet = Utils.VlNetworkPacket(RoomVariables, Id);
|
|
||||||
Send(packet);
|
|
||||||
SetTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetTimer() {
|
|
||||||
if (timer != null) {
|
|
||||||
timer.Stop();
|
|
||||||
timer.Close();
|
|
||||||
}
|
|
||||||
timer = new System.Timers.Timer(
|
|
||||||
random.Next(minTime * 1000, maxTime * 1000)
|
|
||||||
);
|
|
||||||
timer.AutoReset = false;
|
|
||||||
timer.Enabled = true;
|
|
||||||
timer.Elapsed += StartAlert;
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,10 @@ public class Server {
|
|||||||
if (IPv6AndIPv4)
|
if (IPv6AndIPv4)
|
||||||
listener.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
|
listener.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
|
||||||
listener.Bind(new IPEndPoint(ipAddress, port));
|
listener.Bind(new IPEndPoint(ipAddress, port));
|
||||||
new RoomWithAlert("LoungeInt"); // FIXME use config for this
|
Room.GetOrAdd("LoungeInt").AddAlert(new Room.AlertInfo("3")); // FIXME use config for this
|
||||||
|
Room.GetOrAdd("Spaceport").AddAlert(new Room.AlertInfo("1", 20.0, 300, 300));
|
||||||
|
Room.GetOrAdd("Spaceport").AddAlert(new Room.AlertInfo("2", 120.0, 1800, 3600));
|
||||||
|
Room.GetOrAdd("Academy").AddAlert(new Room.AlertInfo("1", 20.0, 300, 300));
|
||||||
await Listen(listener);
|
await Listen(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user