support for "WorldEvents" (ship battle)

This commit is contained in:
Robert Paciorek 2024-01-19 20:06:24 +00:00 committed by Spirtix
parent 045a413998
commit 7cc20ae3bb
7 changed files with 343 additions and 7 deletions

View File

@ -9,7 +9,7 @@ class DateTimeHandler : ICommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public void Handle(Client client, NetworkObject receivedObject) {
NetworkObject cmd = new(); NetworkObject cmd = new();
NetworkObject obj = new(); NetworkObject obj = new();
obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm") }); obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss") });
cmd.Add("c", "DT"); cmd.Add("c", "DT");
cmd.Add("p", obj); cmd.Add("p", obj);
client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize()); client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize());

View File

@ -14,9 +14,7 @@ class JoinRoomHandler : ICommandHandler
string roomName = receivedObject.Get<NetworkObject>("p").Get<string>("rn"); string roomName = receivedObject.Get<NetworkObject>("p").Get<string>("rn");
client.LeaveRoom(); client.LeaveRoom();
client.InvalidatePlayerData(); client.InvalidatePlayerData();
if (!Room.Exists(roomName)) room = Room.GetOrAdd(roomName);
Room.Add(roomName);
room = Room.Get(roomName);
Console.WriteLine($"Join Room: {roomName} RoomID: {room.Id} IID: {client.ClientID}"); Console.WriteLine($"Join Room: {roomName} RoomID: {room.Id} IID: {client.ClientID}");
this.client = client; this.client = client;

View File

@ -28,6 +28,25 @@ class LoginHandler : ICommandHandler
NetworkArray r2 = new(); NetworkArray r2 = new();
NetworkArray we = new();
NetworkArray we1 = new();
NetworkArray we2 = new();
we1.Add("WE_ScoutAttack");
we1.Add((Byte)4);
we1.Add(WorldEvent.Get().EventInfo());
we1.Add(false);
we1.Add(true);
we2.Add("WEN_ScoutAttack");
we2.Add((Byte)4);
we2.Add(WorldEvent.Get().EventInfoNext());
we2.Add(false);
we2.Add(true);
we.Add(we1);
we.Add(we2);
r2.Add(1); r2.Add(1);
r2.Add("ADMIN"); r2.Add("ADMIN");
r2.Add("default"); r2.Add("default");
@ -36,7 +55,7 @@ class LoginHandler : ICommandHandler
r2.Add(true); r2.Add(true);
r2.Add((short)0); r2.Add((short)0);
r2.Add((short)1); r2.Add((short)1);
r2.Add(new NetworkArray()); r2.Add(we);
rl.Add(r2); rl.Add(r2);
NetworkArray r3 = new(); NetworkArray r3 = new();

View File

@ -0,0 +1,115 @@
using System.Globalization;
using sodoffmmo.Attributes;
using sodoffmmo.Core;
using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("wex.WES")] // event status request
class WorldEventStatusHandler : ICommandHandler {
public void Handle(Client client, NetworkObject receivedObject) {
client.Send(Utils.ArrNetworkPacket( new string[] {
"WESR",
"WE_ScoutAttack|" + WorldEvent.Get().EventInfo()
}));
}
}
[ExtensionCommandHandler("wex.OV")]
class WorldEventHealthHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.OV","p":{"en":"","event":"ScoutAttack","eventUID":"ZydLUmCC","oh":"0.003444444","uid":"ZydLUmCC1"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
NetworkObject p = receivedObject.Get<NetworkObject>("p");
float healthUpdateVal = float.Parse(
p.Get<string>("oh"),
System.Globalization.CultureInfo.InvariantCulture
);
string targetUid = p.Get<string>("uid");
float health = WorldEvent.Get().UpdateHealth(targetUid, healthUpdateVal);
if (health >= 0.0f) {
// send: {"a":11,"c":0,"p":{"r":367256,"vl":[["WEH_ZydLUmCC1",4,"0.33133352,Thu Jun 22 02:02:43 UTC 2023",false,false]]}}
NetworkPacket packet = Utils.VlNetworkPacket(
"WEH_" + targetUid,
health.ToString("0.0#####", CultureInfo.GetCultureInfo("en-US")) + "," + DateTime.UtcNow.ToString("ddd MMM dd HH:mm:ss UTC yyyy", CultureInfo.GetCultureInfo("en-US"))
);
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
}
}
}
[ExtensionCommandHandler("wex.OVF")] // flare info from ship AI -> resend as WEF_
class WorldEventFlareHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.OVF","p":{"en":"","fuid":"WpnpDyJ51,14,0","oh":"0","ts":"6/29/2023 3:03:18 AM"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
NetworkObject p = receivedObject.Get<NetworkObject>("p");
// send: {"a":11,"c":0,"p":{"r":403777,"vl":[["WEF_WpnpDyJ51,14,0",4,"0,6/29/2023 3:03:18 AM",false,false]]}}
NetworkPacket packet = Utils.VlNetworkPacket(
"WEF_" + p.Get<string>("fuid"),
p.Get<string>("oh") + "," + p.Get<string>("ts")
);
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
}
}
[ExtensionCommandHandler("wex.ST")] // missile info from ship AI -> resend as WA
class WorldEventMissileHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.ST","p":{"en":"","objID":"-4X_gWAo1","tID":"f5b6254a-df78-4e24-aa9d-7e14539fb858","uID":"1f8eeb6b-753f-4e7f-af13-42cdd69d14e7","wID":"5"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
NetworkObject p = receivedObject.Get<NetworkObject>("p");
// send: {"a":13,"c":1,"p":{"c":"","p":{"arr":["WA","1f8eeb6b-753f-4e7f-af13-42cdd69d14e7","5","f5b6254a-df78-4e24-aa9d-7e14539fb858","-4X_gWAo1"]}}}
NetworkPacket packet = Utils.ArrNetworkPacket(new string[] {
"WA",
p.Get<string>("uID"),
p.Get<string>("wID"),
p.Get<string>("tID"),
p.Get<string>("objID")
});
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
}
}
[ExtensionCommandHandler("wex.PS")]
class WorldEventScoreHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.PS","p":{"ScoreData":"Datashyo/10","en":"","id":"ScoutAttack"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
string scoreData = receivedObject.Get<NetworkObject>("p").Get<string>("ScoreData");
WorldEvent.Get().UpdateScore(client, scoreData);
}
}
[ExtensionCommandHandler("wex.AIACK")] // AI ack
class WorldEventAIACKHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.AIACK","p":{"en":"","id":"f322dd98-e9fb-4b2d-a5e0-1c98680517b5","uid":"SoDOff1"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
WorldEvent.Get().UpdateAI(client);
}
}
[ExtensionCommandHandler("wex.AIP")] // AI ping
class WorldEventAIPingHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.AIP","p":{"en":""},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
WorldEvent.Get().UpdateAI(client);
}
}
[ExtensionCommandHandler("wex.ETS")] // time span
class WorldEventTimeSpanHandler : ICommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.ETS","p":{"en":"","timeSpan":"300"},"r":-1}}
public void Handle(Client client, NetworkObject receivedObject) {
float timeSpan = float.Parse(
receivedObject.Get<NetworkObject>("p").Get<string>("timeSpan"),
System.Globalization.CultureInfo.InvariantCulture
);
WorldEvent.Get().SetTimeSpan(client, timeSpan);
}
}

View File

@ -39,6 +39,12 @@ public class Room {
public static Room Get(string name) => rooms[name]; public static Room Get(string name) => rooms[name];
public static Room GetOrAdd(string name) {
if (!Room.Exists(name))
Room.Add(name);
return rooms[name];
}
public static bool Exists(string name) => rooms.ContainsKey(name); public static bool Exists(string name) => rooms.ContainsKey(name);
public static void Add(string name) { public static void Add(string name) {

View File

@ -5,6 +5,8 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using sodoffmmo.Data;
namespace sodoffmmo.Core; namespace sodoffmmo.Core;
internal static class Utils { internal static class Utils {
public static bool VariablesValid(Client client) { public static bool VariablesValid(Client client) {
@ -19,4 +21,32 @@ internal static class Utils {
} }
return true; return true;
} }
public static NetworkPacket VlNetworkPacket(NetworkArray vl2, int roomID) {
NetworkObject wedata = new();
NetworkArray vl = new();
vl.Add(vl2);
wedata.Add("r", roomID);
wedata.Add("vl", vl);
return NetworkObject.WrapObject(0, 11, wedata).Serialize();
}
public static NetworkPacket VlNetworkPacket(string a, string b) {
NetworkArray vl2 = new();
vl2.Add(a);
vl2.Add((Byte)4);
vl2.Add(b);
vl2.Add(false);
vl2.Add(false);
return VlNetworkPacket(vl2, WorldEvent.Get().GetRoom().Id);
}
public static NetworkPacket ArrNetworkPacket(string[] data) {
NetworkObject cmd = new();
NetworkObject obj = new();
obj.Add("arr", data);
cmd.Add("c", "");
cmd.Add("p", obj);
return NetworkObject.WrapObject(1, 13, cmd).Serialize();
}
} }

168
src/Core/WorldEvent.cs Normal file
View File

@ -0,0 +1,168 @@
using System.Globalization;
using sodoffmmo.Data;
namespace sodoffmmo.Core;
class WorldEvent {
private static WorldEvent _instance = null;
private object EventLock = new object();
private Random random = new Random();
public static WorldEvent Get() {
if (_instance == null) {
_instance = new WorldEvent();
}
return _instance;
}
private WorldEvent() {
Reset(0.5f);
}
private string uid;
private Room room;
private DateTime startTime;
private DateTime endTime;
private string startTimeString;
private Dictionary<string, float> health;
private Dictionary<Client, string> players;
private Client operatorAI;
private DateTime AITime;
private bool endTimeIsSet;
private void Reset(float time) {
startTime = DateTime.UtcNow.AddMinutes(time);
startTimeString = startTime.ToString("MM/dd/yyyy HH:mm:ss");
uid = Path.GetRandomFileName().Substring(0, 8); // this is used as RandomSeed for random select ship variant
room = Room.GetOrAdd("HubTrainingDO");
endTime = startTime.AddMinutes(10);
endTimeIsSet = false;
operatorAI = null;
health = new();
players = new();
}
private void InitEvent() {
lock (EventLock) {
if (operatorAI is null || AITime < DateTime.UtcNow) {
var clients = room.Clients.ToList();
operatorAI = clients[random.Next(0, clients.Count)];
AITime = DateTime.UtcNow.AddSeconds(3.5);
} else {
return;
}
}
operatorAI.Send(Utils.VlNetworkPacket("WE__AI", operatorAI.PlayerData.Uid));
Console.WriteLine($"Event AI operator: {operatorAI.PlayerData.Uid}");
}
private bool EndEvent(bool force = false) {
bool results = true;
string targets = "";
foreach (var x in health) {
results = results && (x.Value == 0.0f);
targets += x.Key + ":" + x.Value.ToString("0.0#####", CultureInfo.GetCultureInfo("en-US")) + ",";
}
if (results || force) {
string scores = "";
foreach (var x in players) {
scores += x.Value + ",";
}
NetworkPacket packet = Utils.VlNetworkPacket(
"WE_ScoutAttack_End",
$"{uid};{results};{scores};{targets}"
);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
NetworkObject wedata = new();
NetworkArray vl = new();
NetworkArray vl1 = new();
vl1.Add("WE__AI");
vl1.Add((Byte)0);
vl1.Add("");
vl1.Add(false);
vl1.Add(false);
vl.Add(vl1);
foreach (var t in health) {
NetworkArray vl2 = new();
vl2.Add("WEH_" + t.Key);
vl2.Add((Byte)0);
vl2.Add("");
vl2.Add(false);
vl2.Add(false);
vl.Add(vl2);
NetworkArray vl3 = new();
vl3.Add("WEF_" + t.Key);
vl3.Add((Byte)0);
vl3.Add("");
vl3.Add(false);
vl3.Add(false);
vl.Add(vl3);
}
wedata.Add("r", room.Id);
wedata.Add("vl", vl);
packet = NetworkObject.WrapObject(0, 11, wedata).Serialize();
Reset(5);
return true;
}
return false;
}
public string EventInfo() {
return startTimeString + "," + uid + ", false, HubTrainingDO";
}
public string EventInfoNext() {
return startTimeString; // TODO on og this was different time (real next event?)
}
public string GetUid() => uid;
public Room GetRoom() => room;
public float UpdateHealth(string targetUid, float updateVal) {
InitEvent(); // TODO better place for this
if (!health.ContainsKey(targetUid))
health.Add(targetUid, 1.0f);
health[targetUid] -= updateVal;
if (health[targetUid] < 0) {
health[targetUid] = 0.0f;
if (EndEvent())
return -1.0f;
}
if (endTime < DateTime.UtcNow) {
EndEvent(true);
return -1.0f;
}
return health[targetUid];
}
public void UpdateScore(Client client, string value) {
if (!players.ContainsKey(client)) {
players.Add(client, value);
} else {
players[client] = value;
}
}
public void UpdateAI(Client client) {
if (client == operatorAI)
AITime = DateTime.UtcNow.AddSeconds(7);
}
public void SetTimeSpan(Client client, float seconds) {
if (client == operatorAI || !endTimeIsSet) {
endTime = startTime.AddSeconds(seconds);
endTimeIsSet = true;
}
}
public float GetHealth(string targetUid) => health[targetUid];
}