forked from SoDOff-Project/sodoff-mmo
initial code release
This commit is contained in:
parent
77bdcbc6c9
commit
af5007e3b7
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.vs
|
||||
.vscode
|
||||
.DS_Store
|
||||
src/bin
|
||||
src/obj
|
||||
src/Properties
|
||||
src/sodoffmmo.csproj.user
|
22
sodoff-mmo.sln
Normal file
22
sodoff-mmo.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sodoffmmo", "src\sodoffmmo.csproj", "{049E36E9-29EC-4A15-96A5-99A049BD2F83}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{049E36E9-29EC-4A15-96A5-99A049BD2F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{049E36E9-29EC-4A15-96A5-99A049BD2F83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{049E36E9-29EC-4A15-96A5-99A049BD2F83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{049E36E9-29EC-4A15-96A5-99A049BD2F83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
10
src/Attributes/CommandHandlerAttribute.cs
Normal file
10
src/Attributes/CommandHandlerAttribute.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace sodoffmmo.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
class CommandHandlerAttribute : Attribute {
|
||||
public int ID { get; }
|
||||
|
||||
public CommandHandlerAttribute(int id) {
|
||||
ID = id;
|
||||
}
|
||||
}
|
10
src/Attributes/ExtensionCommandHandlerAttribute.cs
Normal file
10
src/Attributes/ExtensionCommandHandlerAttribute.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace sodoffmmo.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
class ExtensionCommandHandlerAttribute : Attribute {
|
||||
public string Name { get; }
|
||||
|
||||
public ExtensionCommandHandlerAttribute(string name) {
|
||||
Name = name;
|
||||
}
|
||||
}
|
33
src/CommandHandlers/ChatMessageHandler.cs
Normal file
33
src/CommandHandlers/ChatMessageHandler.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("SCM")]
|
||||
class ChatMessageHandler : ICommandHandler {
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
string message = receivedObject.Get<NetworkObject>("p").Get<string>("chm");
|
||||
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject data = new();
|
||||
data.Add("arr", new string[] { "CMR", "-1", client.PlayerData.Uid, "1", message, "", "1", "placeholder" });
|
||||
cmd.Add("c", "CMR");
|
||||
cmd.Add("p", data);
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client) {
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
cmd = new();
|
||||
data = new();
|
||||
data.Add("arr", new string[] { "SCA", "-1", "1", message, "", "1" });
|
||||
cmd.Add("c", "SCA");
|
||||
cmd.Add("p", data);
|
||||
packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
|
||||
client.Send(packet);
|
||||
}
|
||||
}
|
17
src/CommandHandlers/DateTimeHandler.cs
Normal file
17
src/CommandHandlers/DateTimeHandler.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("DT")]
|
||||
class DateTimeHandler : ICommandHandler {
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject obj = new();
|
||||
obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm") });
|
||||
cmd.Add("c", "DT");
|
||||
cmd.Add("p", obj);
|
||||
client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize());
|
||||
}
|
||||
}
|
12
src/CommandHandlers/ExitHandler.cs
Normal file
12
src/CommandHandlers/ExitHandler.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[CommandHandler(26)]
|
||||
class ExitHandler : ICommandHandler {
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
client.LeaveRoom();
|
||||
}
|
||||
}
|
41
src/CommandHandlers/HandshakeHandler.cs
Normal file
41
src/CommandHandlers/HandshakeHandler.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[CommandHandler(0)]
|
||||
class HandshakeHandler : ICommandHandler
|
||||
{
|
||||
public void Handle(Client client, NetworkObject receivedObject)
|
||||
{
|
||||
string? token = receivedObject.Get<string>("rt");
|
||||
if (token != null) {
|
||||
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkObject obj = new();
|
||||
|
||||
obj.Add("tk", RandomString(32));
|
||||
obj.Add("ct", 1024);
|
||||
obj.Add("ms", 1000000);
|
||||
|
||||
client.Send(NetworkObject.WrapObject(0, 0, obj).Serialize());
|
||||
}
|
||||
|
||||
private string RandomString(int length) {
|
||||
Random random = new Random();
|
||||
const string pool = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var builder = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var c = pool[random.Next(0, pool.Length)];
|
||||
builder.Append(c);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
106
src/CommandHandlers/JoinRoomHandler.cs
Normal file
106
src/CommandHandlers/JoinRoomHandler.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("JA")]
|
||||
class JoinRoomHandler : ICommandHandler
|
||||
{
|
||||
Room room;
|
||||
Client client;
|
||||
public void Handle(Client client, NetworkObject receivedObject)
|
||||
{
|
||||
string roomName = receivedObject.Get<NetworkObject>("p").Get<string>("rn");
|
||||
client.LeaveRoom();
|
||||
client.InvalidatePlayerData();
|
||||
if (!Room.Exists(roomName))
|
||||
Room.Add(roomName);
|
||||
room = Room.Get(roomName);
|
||||
Console.WriteLine($"Join Room: {roomName} RoomID: {room.Id} IID: {client.internalId}");
|
||||
this.client = client;
|
||||
|
||||
RespondJoinRoom();
|
||||
SubscribeRoom();
|
||||
UpdatePlayerUserVariables();
|
||||
client.Room = room;
|
||||
}
|
||||
|
||||
private void RespondJoinRoom() {
|
||||
NetworkObject obj = new();
|
||||
NetworkArray roomInfo = new();
|
||||
roomInfo.Add(room.Id);
|
||||
roomInfo.Add(room.Name); // Room Name
|
||||
roomInfo.Add(room.Name); // Group Name
|
||||
roomInfo.Add(true);
|
||||
roomInfo.Add(false);
|
||||
roomInfo.Add(false);
|
||||
roomInfo.Add((short)24);
|
||||
roomInfo.Add((short)27);
|
||||
roomInfo.Add(new NetworkArray());
|
||||
roomInfo.Add((short)0);
|
||||
roomInfo.Add((short)0);
|
||||
|
||||
NetworkArray userList = new();
|
||||
foreach (Client player in room.Clients) {
|
||||
userList.Add(player.PlayerData.GetNetworkData());
|
||||
}
|
||||
|
||||
obj.Add("r", roomInfo);
|
||||
obj.Add("ul", userList);
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(0, 4, obj).Serialize();
|
||||
packet.Compress();
|
||||
client.Send(packet);
|
||||
}
|
||||
|
||||
private void SubscribeRoom() {
|
||||
NetworkObject obj = new();
|
||||
NetworkArray list = new();
|
||||
|
||||
NetworkArray r1 = new();
|
||||
r1.Add(room.Id);
|
||||
r1.Add(room.Name); // Room Name
|
||||
r1.Add(room.Name); // Group Name
|
||||
r1.Add(true);
|
||||
r1.Add(false);
|
||||
r1.Add(false);
|
||||
r1.Add((short)24);
|
||||
r1.Add((short)27);
|
||||
r1.Add(new NetworkArray());
|
||||
r1.Add((short)0);
|
||||
r1.Add((short)0);
|
||||
|
||||
NetworkArray r2 = new();
|
||||
r2.Add(room.Id);
|
||||
r2.Add(room.Name); // Room Name
|
||||
r2.Add(room.Name); // Group Name
|
||||
r2.Add(true);
|
||||
r2.Add(false);
|
||||
r2.Add(false);
|
||||
r2.Add((short)7);
|
||||
r2.Add((short)27);
|
||||
r2.Add(new NetworkArray());
|
||||
r2.Add((short)0);
|
||||
r2.Add((short)0);
|
||||
|
||||
list.Add(r1);
|
||||
list.Add(r2);
|
||||
|
||||
obj.Add("rl", list);
|
||||
obj.Add("g", room.Name);
|
||||
client.Send(NetworkObject.WrapObject(0, 15, obj).Serialize());
|
||||
}
|
||||
|
||||
private void UpdatePlayerUserVariables() {
|
||||
foreach (Client c in room.Clients) {
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject obj = new();
|
||||
cmd.Add("c", "SUV");
|
||||
obj.Add("MID", c.PlayerData.Id);
|
||||
cmd.Add("p", obj);
|
||||
client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
63
src/CommandHandlers/LoginHandler.cs
Normal file
63
src/CommandHandlers/LoginHandler.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[CommandHandler(1)]
|
||||
class LoginHandler : ICommandHandler
|
||||
{
|
||||
public void Handle(Client client, NetworkObject receivedObject)
|
||||
{
|
||||
NetworkArray rl = new();
|
||||
|
||||
NetworkArray r1 = new();
|
||||
r1.Add(0);
|
||||
r1.Add("MP_SYS");
|
||||
r1.Add("default");
|
||||
r1.Add(true);
|
||||
r1.Add(false);
|
||||
r1.Add(false);
|
||||
r1.Add((short)0);
|
||||
r1.Add((short)10);
|
||||
r1.Add(new NetworkArray());
|
||||
r1.Add((short)0);
|
||||
r1.Add((short)0);
|
||||
rl.Add(r1);
|
||||
|
||||
NetworkArray r2 = new();
|
||||
|
||||
r2.Add(1);
|
||||
r2.Add("ADMIN");
|
||||
r2.Add("default");
|
||||
r2.Add(false);
|
||||
r2.Add(false);
|
||||
r2.Add(true);
|
||||
r2.Add((short)0);
|
||||
r2.Add((short)1);
|
||||
r2.Add(new NetworkArray());
|
||||
rl.Add(r2);
|
||||
|
||||
NetworkArray r3 = new();
|
||||
r3.Add(2);
|
||||
r3.Add("LIMBO");
|
||||
r3.Add("default");
|
||||
r3.Add(false);
|
||||
r3.Add(false);
|
||||
r3.Add(false);
|
||||
r3.Add((short)31);
|
||||
r3.Add((short)10000);
|
||||
r3.Add(new NetworkArray());
|
||||
rl.Add(r3);
|
||||
|
||||
NetworkObject content = new();
|
||||
content.Add("rl", rl);
|
||||
content.Add("zn", "JumpStart");
|
||||
content.Add("rs", (short)5);
|
||||
content.Add("un", "005fd387-c264-410f-acf3-dbe3a06aaffa");
|
||||
content.Add("id", 1143760);
|
||||
content.Add("pi", (short)1);
|
||||
|
||||
client.Send(NetworkObject.WrapObject(0, 1, content).Serialize());
|
||||
}
|
||||
}
|
17
src/CommandHandlers/PingHandler.cs
Normal file
17
src/CommandHandlers/PingHandler.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("PNG")]
|
||||
class PingHandler : ICommandHandler {
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject obj = new();
|
||||
obj.Add("arr", new string[] { "PNG", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString() });
|
||||
cmd.Add("c", "PNG");
|
||||
cmd.Add("p", obj);
|
||||
client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize());
|
||||
}
|
||||
}
|
62
src/CommandHandlers/SetPositionVariablesHandler.cs
Normal file
62
src/CommandHandlers/SetPositionVariablesHandler.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("SPV")]
|
||||
class SetPositionVariablesHandler : ICommandHandler {
|
||||
Client client;
|
||||
NetworkObject spvData;
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
this.client = client;
|
||||
spvData = receivedObject;
|
||||
UpdatePositionVariables();
|
||||
SendSPVCommand();
|
||||
}
|
||||
|
||||
private void UpdatePositionVariables() {
|
||||
NetworkObject obj = spvData.Get<NetworkObject>("p");
|
||||
float[] pos = obj.Get<float[]>("U");
|
||||
client.PlayerData.R = obj.Get<float>("R");
|
||||
client.PlayerData.P1 = pos[0];
|
||||
client.PlayerData.P2 = pos[1];
|
||||
client.PlayerData.P3 = pos[2];
|
||||
client.PlayerData.R1 = pos[3];
|
||||
client.PlayerData.R2 = pos[4];
|
||||
client.PlayerData.R3 = pos[5];
|
||||
client.PlayerData.Mx = obj.Get<float>("MX");
|
||||
client.PlayerData.F = obj.Get<int>("F");
|
||||
client.PlayerData.Mbf = obj.Get<int>("MBF");
|
||||
}
|
||||
|
||||
private void SendSPVCommand() {
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject obj = new();
|
||||
NetworkArray container = new();
|
||||
NetworkObject vars = new();
|
||||
vars.Add("MX", (float)client.PlayerData.Mx);
|
||||
vars.Add("ST", Runtime.CurrentRuntime);
|
||||
vars.Add("NT", Runtime.CurrentRuntime.ToString());
|
||||
vars.Add("t", (int)(Runtime.CurrentRuntime / 1000));
|
||||
vars.Add("F", client.PlayerData.F);
|
||||
vars.Add("MBF", client.PlayerData.Mbf);
|
||||
vars.Add("R", client.PlayerData.R);
|
||||
vars.Add("U", new float[] { (float)client.PlayerData.P1, (float)client.PlayerData.P2, (float)client.PlayerData.P3, (float)client.PlayerData.R1, (float)client.PlayerData.R2, (float)client.PlayerData.R3 });
|
||||
vars.Add("MID", client.PlayerData.Id);
|
||||
|
||||
container.Add(vars);
|
||||
obj.Add("arr", container);
|
||||
cmd.Add("c", "SPV");
|
||||
cmd.Add("p", obj);
|
||||
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
|
||||
lock (client.Room.roomLock) {
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client)
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
170
src/CommandHandlers/SetUserVariablesHandler.cs
Normal file
170
src/CommandHandlers/SetUserVariablesHandler.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using sodoffmmo.Attributes;
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
using System.Globalization;
|
||||
|
||||
namespace sodoffmmo.CommandHandlers;
|
||||
|
||||
[ExtensionCommandHandler("SUV")]
|
||||
class SetUserVariablesHandler : ICommandHandler {
|
||||
NetworkObject suvData;
|
||||
Client client;
|
||||
string? uid;
|
||||
public void Handle(Client client, NetworkObject receivedObject) {
|
||||
this.client = client;
|
||||
suvData = receivedObject.Get<NetworkObject>("p");
|
||||
uid = suvData.Get<string>("UID");
|
||||
|
||||
// TODO
|
||||
if (uid != null && client.PlayerData.Uid != uid)
|
||||
ProcessPlayerData();
|
||||
else
|
||||
UpdateVars();
|
||||
|
||||
}
|
||||
|
||||
private void ProcessPlayerData() {
|
||||
client.PlayerData.Uid = uid;
|
||||
client.PlayerData.A = suvData.Get<string>("A");
|
||||
client.PlayerData.Cu = suvData.Get<string>("CU");
|
||||
client.PlayerData.M = suvData.Get<string>("M");
|
||||
client.PlayerData.L = suvData.Get<string>("L");
|
||||
client.PlayerData.Ra = suvData.Get<string>("RA");
|
||||
string udt = suvData.Get<string>("UDT");
|
||||
if (udt != null)
|
||||
client.PlayerData.Udt = udt;
|
||||
client.PlayerData.P1 = double.Parse(suvData.Get<string>("P1"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.P2 = double.Parse(suvData.Get<string>("P2"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.P3 = double.Parse(suvData.Get<string>("P3"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.R1 = double.Parse(suvData.Get<string>("R1"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.R2 = double.Parse(suvData.Get<string>("R2"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.R3 = double.Parse(suvData.Get<string>("R3"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.R = double.Parse(suvData.Get<string>("R"), CultureInfo.InvariantCulture);
|
||||
client.PlayerData.Mbf = int.Parse(suvData.Get<string>("MBF"));
|
||||
client.PlayerData.F = int.Parse(suvData.Get<string>("F"));
|
||||
client.PlayerData.J = suvData.Get<string>("J");
|
||||
client.PlayerData.Bu = suvData.Get<string>("BU");
|
||||
client.PlayerData.Fp = suvData.Get<string>("FP");
|
||||
client.PlayerData.Id = client.Room.NextPlayerId();
|
||||
Console.WriteLine($"SUV {client.Room.Name} IID: {client.internalId}");
|
||||
client.Room.AddClient(client);
|
||||
UpdatePlayersInRoom();
|
||||
SendSUVToPlayerInRoom();
|
||||
}
|
||||
|
||||
private void UpdateVars() {
|
||||
string? FP = suvData.Get<string>("FP");
|
||||
string? PU = suvData.Get<string>("PU");
|
||||
string? L = suvData.Get<string>("L");
|
||||
if (FP is null && PU is null && L is null) {
|
||||
return; // TODO
|
||||
}
|
||||
NetworkObject data = new();
|
||||
NetworkObject data2 = new();
|
||||
data.Add("u", client.PlayerData.Id);
|
||||
|
||||
NetworkArray vl = new();
|
||||
if (FP != null) {
|
||||
client.PlayerData.Fp = FP;
|
||||
data2.Add("FP", client.PlayerData.Fp);
|
||||
vl.Add(NetworkArray.StringParam("FP", client.PlayerData.Fp));
|
||||
}
|
||||
if (PU != null) {
|
||||
client.PlayerData.Pu = PU;
|
||||
data2.Add("PU", client.PlayerData.Pu);
|
||||
vl.Add(NetworkArray.StringParam("PU", client.PlayerData.Pu));
|
||||
}
|
||||
if (L != null) {
|
||||
client.PlayerData.L = L;
|
||||
data2.Add("L", client.PlayerData.L);
|
||||
vl.Add(NetworkArray.StringParam("L", client.PlayerData.L));
|
||||
}
|
||||
data.Add("vl", vl);
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(0, 12, data).Serialize();
|
||||
lock (client.Room.roomLock) {
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client)
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkObject cmd = new();
|
||||
cmd.Add("c", "SUV");
|
||||
|
||||
NetworkObject container = new();
|
||||
|
||||
NetworkArray arr = new();
|
||||
data2.Add("RID", "1");
|
||||
data2.Add("MID", client.PlayerData.Id);
|
||||
arr.Add(data2);
|
||||
container.Add("arr", arr);
|
||||
cmd.Add("p", container);
|
||||
packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client)
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePlayersInRoom() {
|
||||
NetworkObject data = new();
|
||||
data.Add("r", client.Room.Id);
|
||||
|
||||
NetworkArray user = new();
|
||||
user.Add(client.PlayerData.Id);
|
||||
user.Add(client.PlayerData.Uid);
|
||||
user.Add((short)1);
|
||||
user.Add((short)client.PlayerData.Id);
|
||||
|
||||
NetworkArray playerData = new();
|
||||
playerData.Add(NetworkArray.DoubleParam("R1", client.PlayerData.R1));
|
||||
playerData.Add(NetworkArray.StringParam("FP", client.PlayerData.Fp));
|
||||
playerData.Add(NetworkArray.DoubleParam("MX", client.PlayerData.Mx));
|
||||
playerData.Add(NetworkArray.StringParam("UDT", client.PlayerData.Udt));
|
||||
playerData.Add(NetworkArray.DoubleParam("P2", client.PlayerData.P2));
|
||||
playerData.Add(NetworkArray.DoubleParam("NT", Runtime.CurrentRuntime));
|
||||
playerData.Add(NetworkArray.IntParam("t", (int)(Runtime.CurrentRuntime / 1000)));
|
||||
playerData.Add(NetworkArray.StringParam("J", client.PlayerData.J));
|
||||
playerData.Add(NetworkArray.IntParam("F", client.PlayerData.F));
|
||||
playerData.Add(NetworkArray.IntParam("MBF", client.PlayerData.Mbf));
|
||||
playerData.Add(NetworkArray.DoubleParam("R2", client.PlayerData.R2));
|
||||
playerData.Add(NetworkArray.DoubleParam("R", client.PlayerData.R));
|
||||
playerData.Add(NetworkArray.StringParam("BU", client.PlayerData.Bu));
|
||||
playerData.Add(NetworkArray.DoubleParam("P1", client.PlayerData.P1));
|
||||
playerData.Add(NetworkArray.StringParam("UID", client.PlayerData.Uid));
|
||||
playerData.Add(NetworkArray.DoubleParam("R3", client.PlayerData.R3));
|
||||
playerData.Add(NetworkArray.StringParam("PU", client.PlayerData.Pu));
|
||||
playerData.Add(NetworkArray.StringParam("A", client.PlayerData.A));
|
||||
playerData.Add(NetworkArray.StringParam("RA", client.PlayerData.Ra));
|
||||
playerData.Add(NetworkArray.DoubleParam("P3", client.PlayerData.P3));
|
||||
playerData.Add(NetworkArray.StringParam("CU", client.PlayerData.Cu));
|
||||
playerData.Add(NetworkArray.StringParam("M", client.PlayerData.M));
|
||||
playerData.Add(NetworkArray.StringParam("L", client.PlayerData.L));
|
||||
|
||||
user.Add(playerData);
|
||||
data.Add("u", user);
|
||||
NetworkPacket packet = NetworkObject.WrapObject(0, 1000, data).Serialize();
|
||||
packet.Compress();
|
||||
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client)
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendSUVToPlayerInRoom() {
|
||||
NetworkObject cmd = new();
|
||||
NetworkObject obj = new();
|
||||
|
||||
cmd.Add("c", "SUV");
|
||||
obj.Add("MID", client.PlayerData.Id);
|
||||
cmd.Add("p", obj);
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
|
||||
foreach (var roomClient in client.Room.Clients) {
|
||||
if (roomClient != client.Room.Clients)
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
}
|
||||
}
|
84
src/Core/Client.cs
Normal file
84
src/Core/Client.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using sodoffmmo.Data;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace sodoffmmo.Core;
|
||||
public class Client {
|
||||
static int id;
|
||||
static object lck = new(); // For debugging purposes
|
||||
public int internalId; // ---
|
||||
public PlayerData PlayerData { get; set; } = new();
|
||||
public Room Room { get; set; }
|
||||
|
||||
private readonly Socket socket;
|
||||
private NetworkData? lastData;
|
||||
private NetworkPacket? incompleteData;
|
||||
private bool hasIncompletePakcet = false;
|
||||
|
||||
public Client(Socket clientSocket) {
|
||||
socket = clientSocket;
|
||||
lock (lck) {
|
||||
internalId = ++id;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Receive() {
|
||||
byte[] buffer = new byte[2048];
|
||||
int len = await socket.ReceiveAsync(buffer, SocketFlags.None);
|
||||
if (len == 0)
|
||||
throw new SocketException();
|
||||
lastData = new NetworkData(buffer);
|
||||
}
|
||||
|
||||
public bool TryGetNextPacket(out NetworkPacket packet) {
|
||||
packet = new();
|
||||
if (hasIncompletePakcet) {
|
||||
// TODO
|
||||
}
|
||||
byte header = lastData!.ReadByte();
|
||||
if (header != 0x80 && header != 0xa0)
|
||||
return false;
|
||||
short length = lastData.ReadShort();
|
||||
byte[] data = lastData.ReadChunk(length);
|
||||
packet = new NetworkPacket(header, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Send(NetworkPacket packet) {
|
||||
socket.Send(packet.SendData);
|
||||
}
|
||||
|
||||
public void LeaveRoom() {
|
||||
if (Room != null) {
|
||||
Console.WriteLine($"Leave room {Room.Name} IID: {internalId}");
|
||||
Room.RemoveClient(this);
|
||||
NetworkObject data = new();
|
||||
data.Add("r", Room.Id);
|
||||
data.Add("u", PlayerData.Id);
|
||||
|
||||
NetworkPacket packet = NetworkObject.WrapObject(0, 1004, data).Serialize();
|
||||
foreach (var roomClient in Room.Clients) {
|
||||
roomClient.Send(packet);
|
||||
}
|
||||
Room = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidatePlayerData() {
|
||||
PlayerData = new();
|
||||
}
|
||||
|
||||
public void Disconnect() {
|
||||
try {
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
} finally {
|
||||
socket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Connected {
|
||||
get {
|
||||
return socket.Connected;
|
||||
}
|
||||
}
|
||||
}
|
6
src/Core/ICommandHandler.cs
Normal file
6
src/Core/ICommandHandler.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using sodoffmmo.Data;
|
||||
|
||||
namespace sodoffmmo.Core;
|
||||
public interface ICommandHandler {
|
||||
public void Handle(Client client, NetworkObject receivedObject);
|
||||
}
|
50
src/Core/ModuleManager.cs
Normal file
50
src/Core/ModuleManager.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System.Reflection;
|
||||
using sodoffmmo.Attributes;
|
||||
|
||||
namespace sodoffmmo.Core;
|
||||
|
||||
class ModuleManager {
|
||||
Dictionary<int, Type> handlers = new();
|
||||
Dictionary<string, Type> extHandlers = new();
|
||||
|
||||
public void RegisterModules() {
|
||||
RegisterHandlers();
|
||||
RegisterExtensionHandlers();
|
||||
}
|
||||
|
||||
public ICommandHandler GetCommandHandler(int id) {
|
||||
if (handlers.TryGetValue(id, out Type? handler))
|
||||
return (ICommandHandler)Activator.CreateInstance(handler)!;
|
||||
throw new Exception($"Command handler with ID {id} not found!");
|
||||
}
|
||||
|
||||
public ICommandHandler GetCommandHandler(string name) {
|
||||
if (extHandlers.TryGetValue(name, out Type? handler))
|
||||
return (ICommandHandler)Activator.CreateInstance(handler)!;
|
||||
throw new Exception($"Command handler with name \"{name}\" not found!");
|
||||
}
|
||||
|
||||
private void RegisterHandlers() {
|
||||
handlers.Clear();
|
||||
var handlerTypes = Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(type => typeof(ICommandHandler).IsAssignableFrom(type))
|
||||
.Where(type => type.GetCustomAttribute<CommandHandlerAttribute>() != null);
|
||||
|
||||
foreach (var handlerType in handlerTypes) {
|
||||
CommandHandlerAttribute attrib = (handlerType.GetCustomAttribute(typeof(CommandHandlerAttribute)) as CommandHandlerAttribute)!;
|
||||
handlers[attrib.ID] = handlerType;
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterExtensionHandlers() {
|
||||
extHandlers.Clear();
|
||||
var extHandlerTypes = Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(type => typeof(ICommandHandler).IsAssignableFrom(type))
|
||||
.Where(type => type.GetCustomAttribute<ExtensionCommandHandlerAttribute>() != null);
|
||||
|
||||
foreach (var extHandlerType in extHandlerTypes) {
|
||||
ExtensionCommandHandlerAttribute attrib = (extHandlerType.GetCustomAttribute(typeof(ExtensionCommandHandlerAttribute)) as ExtensionCommandHandlerAttribute)!;
|
||||
extHandlers[attrib.Name] = extHandlerType;
|
||||
}
|
||||
}
|
||||
}
|
47
src/Core/Room.cs
Normal file
47
src/Core/Room.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
|
||||
namespace sodoffmmo.Core;
|
||||
public class Room {
|
||||
static int playerId = 0;
|
||||
static int roomId = 0;
|
||||
static Dictionary<string, Room> rooms = new();
|
||||
public object roomLock = new object();
|
||||
|
||||
List<Client> clients = new();
|
||||
|
||||
public string Name { get; private set; }
|
||||
public int Id { get; private set; }
|
||||
|
||||
public Room(int id, string name) {
|
||||
Name = name;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public IEnumerable<Client> Clients {
|
||||
get {
|
||||
return new List<Client>(clients);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddClient(Client client) {
|
||||
lock (roomLock) {
|
||||
clients.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveClient(Client client) {
|
||||
lock (roomLock) {
|
||||
clients.Remove(client);
|
||||
}
|
||||
}
|
||||
|
||||
public int NextPlayerId() => ++playerId;
|
||||
|
||||
public static Room Get(string name) => rooms[name];
|
||||
|
||||
public static bool Exists(string name) => rooms.ContainsKey(name);
|
||||
|
||||
public static void Add(string name) {
|
||||
rooms[name] = new Room(rooms.Count + 1, name);
|
||||
}
|
||||
}
|
20
src/Core/Runtime.cs
Normal file
20
src/Core/Runtime.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace sodoffmmo.Core;
|
||||
public static class Runtime {
|
||||
static Runtime() {
|
||||
var currentProcess = Process.GetCurrentProcess();
|
||||
lastSystemTime = (long)(DateTime.Now - currentProcess.StartTime).TotalMilliseconds;
|
||||
currentProcess.Dispose();
|
||||
stopwatch = new Stopwatch(); stopwatch.Start();
|
||||
}
|
||||
|
||||
private static long lastSystemTime;
|
||||
private static Stopwatch stopwatch;
|
||||
|
||||
public static long CurrentRuntime {
|
||||
get {
|
||||
return stopwatch.ElapsedMilliseconds + lastSystemTime;
|
||||
}
|
||||
}
|
||||
}
|
55
src/Data/DataDecoder.cs
Normal file
55
src/Data/DataDecoder.cs
Normal file
@ -0,0 +1,55 @@
|
||||
namespace sodoffmmo.Data;
|
||||
|
||||
internal static class DataDecoder {
|
||||
internal static DataWrapper DecodeNull(NetworkData data) => new DataWrapper(NetworkDataType.Null, null!);
|
||||
|
||||
internal static DataWrapper DecodeBool(NetworkData data) => new DataWrapper(NetworkDataType.Bool, data.ReadBool());
|
||||
|
||||
internal static DataWrapper DecodeByte(NetworkData data) => new DataWrapper(NetworkDataType.Byte, data.ReadByte());
|
||||
|
||||
internal static DataWrapper DecodeShort(NetworkData data) => new DataWrapper(NetworkDataType.Short, data.ReadShort());
|
||||
|
||||
internal static DataWrapper DecodeInt(NetworkData data) => new DataWrapper(NetworkDataType.Int, data.ReadInt());
|
||||
|
||||
internal static DataWrapper DecodeLong(NetworkData data) => new DataWrapper(NetworkDataType.Long, data.ReadLong());
|
||||
|
||||
internal static DataWrapper DecodeFloat(NetworkData data) => new DataWrapper(NetworkDataType.Float, data.ReadFloat());
|
||||
|
||||
internal static DataWrapper DecodeDouble(NetworkData data) => new DataWrapper(NetworkDataType.Double, data.ReadDouble());
|
||||
|
||||
internal static DataWrapper DecodeString(NetworkData data) => new DataWrapper(NetworkDataType.String, data.ReadString());
|
||||
|
||||
internal static DataWrapper DecodeByteArray(NetworkData data) {
|
||||
int count = data.ReadInt();
|
||||
return new DataWrapper(NetworkDataType.ByteArray, data.ReadChunk(count));
|
||||
}
|
||||
|
||||
internal static DataWrapper DecodeBoolArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.BoolArray, DecodeTypedArray(data, d => d.ReadBool()));
|
||||
|
||||
internal static DataWrapper DecodeShortArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.ShortArray, DecodeTypedArray(data, d => d.ReadShort()));
|
||||
|
||||
internal static DataWrapper DecodeIntArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.IntArray, DecodeTypedArray(data, d => d.ReadInt()));
|
||||
|
||||
internal static DataWrapper DecodeLongArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.LongArray, DecodeTypedArray(data, d => d.ReadLong()));
|
||||
|
||||
internal static DataWrapper DecodeFloatArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.FloatArray, DecodeTypedArray(data, d => d.ReadFloat()));
|
||||
|
||||
internal static DataWrapper DecodeDoubleArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.DoubleArray, DecodeTypedArray(data, d => d.ReadDouble()));
|
||||
|
||||
internal static DataWrapper DecodeStringArray(NetworkData data)
|
||||
=> new DataWrapper(NetworkDataType.IntArray, DecodeTypedArray(data, d => d.ReadString()));
|
||||
|
||||
private static T[] DecodeTypedArray<T>(NetworkData data, Func<NetworkData, T> readFunction) {
|
||||
short length = data.ReadShort();
|
||||
T[] arr = new T[length];
|
||||
for (short i = 0; i < length; i++)
|
||||
arr[i] = readFunction(data);
|
||||
return arr;
|
||||
}
|
||||
}
|
132
src/Data/DataEncoder.cs
Normal file
132
src/Data/DataEncoder.cs
Normal file
@ -0,0 +1,132 @@
|
||||
namespace sodoffmmo.Data;
|
||||
internal static class DataEncoder {
|
||||
internal static byte[] EncodeNull() => new byte[] { 0 };
|
||||
|
||||
internal static byte[] EncodeByte(byte value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Byte);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeBool(bool value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Bool);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeShort(short value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Short);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeInt(int value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Int);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeLong(long value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Long);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeFloat(float value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Float);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeDouble(double value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.Double);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeString(string value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.String);
|
||||
data.WriteValue(value);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeBoolArray(bool[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.BoolArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeByteArray(byte[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.ByteArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeShortArray(short[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.ShortArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeIntArray(int[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.IntArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeLongArray(long[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.LongArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeFloatArray(float[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.FloatArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeDoubleArray(double[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.DoubleArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeStringArray(string[] value) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)NetworkDataType.StringArray);
|
||||
data.WriteValue(Convert.ToInt16(value.Length));
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
data.WriteValue(value[i]);
|
||||
return data.Data;
|
||||
}
|
||||
}
|
11
src/Data/DataWrapper.cs
Normal file
11
src/Data/DataWrapper.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace sodoffmmo.Data;
|
||||
public class DataWrapper {
|
||||
|
||||
public int Type { get; private set; }
|
||||
public object Data { get; private set; }
|
||||
|
||||
public DataWrapper(NetworkDataType type, object data) {
|
||||
this.Type = (int)type;
|
||||
this.Data = data;
|
||||
}
|
||||
}
|
128
src/Data/NetworkArray.cs
Normal file
128
src/Data/NetworkArray.cs
Normal file
@ -0,0 +1,128 @@
|
||||
namespace sodoffmmo.Data;
|
||||
public class NetworkArray {
|
||||
List<DataWrapper> arrData = new();
|
||||
|
||||
public DataWrapper this[int i] {
|
||||
get { return arrData[i]; }
|
||||
}
|
||||
|
||||
public int Length {
|
||||
get { return arrData.Count; }
|
||||
}
|
||||
|
||||
public void Add(bool value) => AddObject(NetworkDataType.Bool, value);
|
||||
|
||||
public void Add(byte value) => AddObject(NetworkDataType.Byte, value);
|
||||
|
||||
public void Add(short value) => AddObject(NetworkDataType.Short, value);
|
||||
|
||||
public void Add(int value) => AddObject(NetworkDataType.Int, value);
|
||||
|
||||
public void Add(long value) => AddObject(NetworkDataType.Long, value);
|
||||
|
||||
public void Add(float value) => AddObject(NetworkDataType.Float, value);
|
||||
|
||||
public void Add(double value) => AddObject(NetworkDataType.Double, value);
|
||||
|
||||
public void Add(string value) => AddObject(NetworkDataType.String, value);
|
||||
|
||||
public void Add(bool[] value) => AddObject(NetworkDataType.BoolArray, value);
|
||||
|
||||
public void Add(NetworkData value) => AddObject(NetworkDataType.ByteArray, value.Data);
|
||||
|
||||
public void Add(short[] value) => AddObject(NetworkDataType.ShortArray, value);
|
||||
|
||||
public void Add(int[] value) => AddObject(NetworkDataType.IntArray, value);
|
||||
|
||||
public void Add(long[] value) => AddObject(NetworkDataType.LongArray, value);
|
||||
|
||||
public void Add(float[] value) => AddObject(NetworkDataType.FloatArray, value);
|
||||
|
||||
public void Add(double[] value) => AddObject(NetworkDataType.DoubleArray, value);
|
||||
|
||||
public void Add(string[] value) => AddObject(NetworkDataType.StringArray, value);
|
||||
|
||||
public void Add(NetworkArray value) => AddObject(NetworkDataType.NetworkArray, value);
|
||||
|
||||
public void Add(NetworkObject value) => AddObject(NetworkDataType.NetworkObject, value);
|
||||
|
||||
public void Add(DataWrapper dataWrapper) => arrData.Add(dataWrapper);
|
||||
|
||||
private void AddObject(NetworkDataType dataType, object obj) => Add(new DataWrapper(dataType, obj));
|
||||
|
||||
public T GetValue<T>(int index) {
|
||||
if (index >= arrData.Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
return (T)arrData[index].Data;
|
||||
}
|
||||
|
||||
public bool GetBool(int index) => GetValue<bool>(index);
|
||||
|
||||
public byte GetByte(int index) => GetValue<byte>(index);
|
||||
|
||||
public short GetShort(int index) => GetValue<short>(index);
|
||||
|
||||
public int GetInt(int index) => GetValue<int>(index);
|
||||
|
||||
public long GetLong(int index) => GetValue<long>(index);
|
||||
|
||||
public float GetFloat(int index) => GetValue<float>(index);
|
||||
|
||||
public double GetDouble(int index) => GetValue<double>(index);
|
||||
|
||||
public string GetUtfString(int index) => GetValue<string>(index);
|
||||
|
||||
public bool[] GetBoolArray(int index) => GetValue<bool[]>(index);
|
||||
|
||||
public NetworkData GetNetworkData(int index) => GetValue<NetworkData>(index);
|
||||
|
||||
public short[] GetShortArray(int index) => GetValue<short[]>(index);
|
||||
|
||||
public int[] GetIntArray(int index) => GetValue<int[]>(index);
|
||||
|
||||
public long[] GetLongArray(int index) => GetValue<long[]>(index);
|
||||
|
||||
public float[] GetFloatArray(int index) => GetValue<float[]>(index);
|
||||
|
||||
public double[] GetDoubleArray(int index) => GetValue<double[]>(index);
|
||||
|
||||
public string[] GetStringArray(int index) => GetValue<string[]>(index);
|
||||
|
||||
public NetworkArray GetNetworkArray(int index) => GetValue<NetworkArray>(index);
|
||||
|
||||
public NetworkObject GetNetworkObject(int index) => GetValue<NetworkObject>(index);
|
||||
|
||||
public bool Contains(object obj) {
|
||||
if (obj is NetworkObject || obj is NetworkArray)
|
||||
throw new Exception("Unsupported object type");
|
||||
for (int i = 0; i < arrData.Count; i++) {
|
||||
if (object.Equals(arrData[i], obj))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static NetworkArray DoubleParam(string name, double value) {
|
||||
NetworkArray arr = new();
|
||||
arr.Add(name);
|
||||
arr.Add((byte)3);
|
||||
arr.Add(value);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static NetworkArray StringParam(string name, string value) {
|
||||
NetworkArray arr = new();
|
||||
arr.Add(name);
|
||||
arr.Add((byte)4);
|
||||
arr.Add(value);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static NetworkArray IntParam(string name, int value) {
|
||||
NetworkArray arr = new();
|
||||
arr.Add(name);
|
||||
arr.Add((byte)2);
|
||||
arr.Add(value);
|
||||
return arr;
|
||||
}
|
||||
}
|
125
src/Data/NetworkData.cs
Normal file
125
src/Data/NetworkData.cs
Normal file
@ -0,0 +1,125 @@
|
||||
using System.Text;
|
||||
|
||||
namespace sodoffmmo.Data;
|
||||
public class NetworkData {
|
||||
byte[] data;
|
||||
int offset = 0;
|
||||
|
||||
public byte[] Data {
|
||||
get { return data; }
|
||||
}
|
||||
|
||||
public NetworkData() {
|
||||
data = new byte[0];
|
||||
}
|
||||
|
||||
public NetworkData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void Seek(int offset) {
|
||||
int newOffset = this.offset + offset;
|
||||
if (newOffset >= 0 && newOffset < data.Length)
|
||||
this.offset = newOffset;
|
||||
}
|
||||
|
||||
public byte[] ReverseOrder(byte[] data) {
|
||||
if (!BitConverter.IsLittleEndian) return data;
|
||||
Array.Reverse(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte ReadByte() {
|
||||
return data[offset++];
|
||||
}
|
||||
public byte[] ReadChunk(int count) {
|
||||
byte[] chunk = new byte[count];
|
||||
Buffer.BlockCopy(data, offset, chunk, 0, count);
|
||||
offset += count;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public short ReadShort() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(2));
|
||||
return BitConverter.ToInt16(arr);
|
||||
}
|
||||
|
||||
public ushort ReadUShort() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(2));
|
||||
return BitConverter.ToUInt16(arr);
|
||||
}
|
||||
|
||||
public bool ReadBool() => data[offset++] == 1;
|
||||
|
||||
public int ReadInt() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(4));
|
||||
return BitConverter.ToInt32(arr);
|
||||
}
|
||||
|
||||
public long ReadLong() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(8));
|
||||
return BitConverter.ToInt64(arr);
|
||||
}
|
||||
|
||||
public float ReadFloat() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(4));
|
||||
return BitConverter.ToSingle(arr);
|
||||
}
|
||||
|
||||
public double ReadDouble() {
|
||||
byte[] arr = ReverseOrder(ReadChunk(8));
|
||||
return BitConverter.ToDouble(arr);
|
||||
}
|
||||
|
||||
public string ReadString() {
|
||||
ushort count = ReadUShort();
|
||||
string str = Encoding.UTF8.GetString(data, offset, count);
|
||||
offset += count;
|
||||
return str;
|
||||
}
|
||||
|
||||
public void WriteChunk(byte[] chunk, int offset, int count) {
|
||||
byte[] newData = new byte[data.Length + count];
|
||||
Buffer.BlockCopy(data, 0, newData, 0, data.Length);
|
||||
Buffer.BlockCopy(chunk, offset, newData, data.Length, count);
|
||||
data = newData;
|
||||
}
|
||||
|
||||
public void WriteChunk(byte[] chunk) => WriteChunk(chunk, 0, chunk.Length);
|
||||
|
||||
public void WriteValue(byte b) => WriteChunk(new byte[] { b });
|
||||
|
||||
public void WriteValue(bool b) => WriteChunk(new byte[] { (byte)((!b) ? 0 : 1) });
|
||||
|
||||
public void WriteValue(int i) => WriteChunk(ReverseOrder(BitConverter.GetBytes(i)));
|
||||
|
||||
public void WriteValue(short s) => WriteChunk(ReverseOrder(BitConverter.GetBytes(s)));
|
||||
|
||||
public void WriteValue(ushort us) => WriteChunk(ReverseOrder(BitConverter.GetBytes(us)));
|
||||
|
||||
public void WriteValue(long l) => WriteChunk(ReverseOrder(BitConverter.GetBytes(l)));
|
||||
|
||||
public void WriteValue(float f) => WriteChunk(ReverseOrder(BitConverter.GetBytes(f)));
|
||||
|
||||
public void WriteValue(double d) => WriteChunk(ReverseOrder(BitConverter.GetBytes(d)));
|
||||
|
||||
public void WriteValue(string str) {
|
||||
WriteValue(GetUTFStringLength(str));
|
||||
WriteChunk(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private ushort GetUTFStringLength(string str) {
|
||||
ushort length = 0;
|
||||
foreach (int c in str) {
|
||||
if (c > 0 && c < 128)
|
||||
++length;
|
||||
else if (c > 2047)
|
||||
length += 3;
|
||||
else
|
||||
length += 2;
|
||||
}
|
||||
if (length > 32768)
|
||||
throw new Exception("String is too long");
|
||||
return length;
|
||||
}
|
||||
}
|
23
src/Data/NetworkDataType.cs
Normal file
23
src/Data/NetworkDataType.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace sodoffmmo.Data;
|
||||
|
||||
public enum NetworkDataType {
|
||||
Null,
|
||||
Bool,
|
||||
Byte,
|
||||
Short,
|
||||
Int,
|
||||
Long,
|
||||
Float,
|
||||
Double,
|
||||
String,
|
||||
BoolArray,
|
||||
ByteArray,
|
||||
ShortArray,
|
||||
IntArray,
|
||||
LongArray,
|
||||
FloatArray,
|
||||
DoubleArray,
|
||||
StringArray,
|
||||
NetworkArray,
|
||||
NetworkObject,
|
||||
}
|
198
src/Data/NetworkObject.cs
Normal file
198
src/Data/NetworkObject.cs
Normal file
@ -0,0 +1,198 @@
|
||||
namespace sodoffmmo.Data;
|
||||
public class NetworkObject {
|
||||
Dictionary<string, DataWrapper> fields = new();
|
||||
|
||||
public NetworkObject() {}
|
||||
|
||||
public NetworkObject(NetworkData data) {
|
||||
Deserialize(data);
|
||||
}
|
||||
|
||||
public NetworkObject(byte[] data) : this(new NetworkData(data)) { }
|
||||
|
||||
public void Add(string label, DataWrapper wrapper) => fields[label] = wrapper;
|
||||
|
||||
public void Add(string label, byte value) => fields[label] = new DataWrapper(NetworkDataType.Byte, value);
|
||||
|
||||
public void Add(string label, bool value) => fields[label] = new DataWrapper(NetworkDataType.Bool, value);
|
||||
|
||||
public void Add(string label, short value) => fields[label] = new DataWrapper(NetworkDataType.Short, value);
|
||||
|
||||
public void Add(string label, int value) => fields[label] = new DataWrapper(NetworkDataType.Int, value);
|
||||
|
||||
public void Add(string label, long value) => fields[label] = new DataWrapper(NetworkDataType.Long, value);
|
||||
|
||||
public void Add(string label, float value) => fields[label] = new DataWrapper(NetworkDataType.Float, value);
|
||||
|
||||
public void Add(string label, double value) => fields[label] = new DataWrapper(NetworkDataType.Double, value);
|
||||
|
||||
public void Add(string label, string value) => fields[label] = new DataWrapper(NetworkDataType.String, value);
|
||||
|
||||
public void Add(string label, byte[] value) => fields[label] = new DataWrapper(NetworkDataType.ByteArray, value);
|
||||
|
||||
public void Add(string label, bool[] value) => fields[label] = new DataWrapper(NetworkDataType.BoolArray, value);
|
||||
|
||||
public void Add(string label, short[] value) => fields[label] = new DataWrapper(NetworkDataType.ShortArray, value);
|
||||
|
||||
public void Add(string label, int[] value) => fields[label] = new DataWrapper(NetworkDataType.IntArray, value);
|
||||
|
||||
public void Add(string label, long[] value) => fields[label] = new DataWrapper(NetworkDataType.LongArray, value);
|
||||
|
||||
public void Add(string label, float[] value) => fields[label] = new DataWrapper(NetworkDataType.FloatArray, value);
|
||||
|
||||
public void Add(string label, double[] value) => fields[label] = new DataWrapper(NetworkDataType.DoubleArray, value);
|
||||
|
||||
public void Add(string label, string[] value) => fields[label] = new DataWrapper(NetworkDataType.StringArray, value);
|
||||
|
||||
public void Add(string label, NetworkArray value) => fields[label] = new DataWrapper(NetworkDataType.NetworkArray, value);
|
||||
|
||||
public void Add(string label, NetworkObject value) => fields[label] = new DataWrapper(NetworkDataType.NetworkObject, value);
|
||||
|
||||
public T Get<T>(string key) {
|
||||
if (!fields.ContainsKey(key))
|
||||
return default;
|
||||
return (T)fields[key].Data;
|
||||
}
|
||||
|
||||
|
||||
public NetworkPacket Serialize() => new NetworkPacket(0x80, SerializeObject(this));
|
||||
|
||||
private byte[] SerializeObject(NetworkObject obj) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)18);
|
||||
data.WriteValue(Convert.ToInt16(obj.fields.Count));
|
||||
foreach (string key in obj.fields.Keys) {
|
||||
data.WriteValue(key);
|
||||
data.WriteChunk(EncodeObject(obj.fields[key]));
|
||||
}
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
private void Deserialize(NetworkData data) {
|
||||
if (data.ReadByte() != 0x12)
|
||||
throw new Exception("Invalid object type");
|
||||
|
||||
short count = data.ReadShort();
|
||||
for (short i = 0; i < count; i++) {
|
||||
string label = data.ReadString();
|
||||
DataWrapper obj = DecodeObject(data);
|
||||
Add(label, obj);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] EncodeObject(DataWrapper obj) {
|
||||
switch ((NetworkDataType)obj.Type) {
|
||||
case NetworkDataType.Null:
|
||||
return DataEncoder.EncodeNull();
|
||||
case NetworkDataType.Bool:
|
||||
return DataEncoder.EncodeBool((bool)obj.Data);
|
||||
case NetworkDataType.Byte:
|
||||
return DataEncoder.EncodeByte((byte)obj.Data);
|
||||
case NetworkDataType.Short:
|
||||
return DataEncoder.EncodeShort((short)obj.Data);
|
||||
case NetworkDataType.Int:
|
||||
return DataEncoder.EncodeInt((int)obj.Data);
|
||||
case NetworkDataType.Long:
|
||||
return DataEncoder.EncodeLong((long)obj.Data);
|
||||
case NetworkDataType.Float:
|
||||
return DataEncoder.EncodeFloat((float)obj.Data);
|
||||
case NetworkDataType.Double:
|
||||
return DataEncoder.EncodeDouble((double)obj.Data);
|
||||
case NetworkDataType.String:
|
||||
return DataEncoder.EncodeString((string)obj.Data);
|
||||
case NetworkDataType.BoolArray:
|
||||
return DataEncoder.EncodeBoolArray((bool[])obj.Data);
|
||||
case NetworkDataType.ByteArray:
|
||||
return DataEncoder.EncodeByteArray((byte[])obj.Data);
|
||||
case NetworkDataType.ShortArray:
|
||||
return DataEncoder.EncodeShortArray((short[])obj.Data);
|
||||
case NetworkDataType.IntArray:
|
||||
return DataEncoder.EncodeIntArray((int[])obj.Data);
|
||||
case NetworkDataType.LongArray:
|
||||
return DataEncoder.EncodeLongArray((long[])obj.Data);
|
||||
case NetworkDataType.FloatArray:
|
||||
return DataEncoder.EncodeFloatArray((float[])obj.Data);
|
||||
case NetworkDataType.DoubleArray:
|
||||
return DataEncoder.EncodeDoubleArray((double[])obj.Data);
|
||||
case NetworkDataType.StringArray:
|
||||
return DataEncoder.EncodeStringArray((string[])obj.Data);
|
||||
case NetworkDataType.NetworkArray:
|
||||
return EncodeNetworkArray((NetworkArray)obj.Data);
|
||||
case NetworkDataType.NetworkObject:
|
||||
return SerializeObject((NetworkObject)obj.Data);
|
||||
default: throw new Exception("Invalid object");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] EncodeNetworkArray(NetworkArray arr) {
|
||||
NetworkData data = new();
|
||||
data.WriteValue((byte)17);
|
||||
data.WriteValue(Convert.ToInt16(arr.Length));
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
data.WriteChunk(EncodeObject(arr[i]));
|
||||
return data.Data;
|
||||
}
|
||||
|
||||
private DataWrapper DecodeObject(NetworkData data) {
|
||||
switch ((NetworkDataType)data.ReadByte()) {
|
||||
case NetworkDataType.Null:
|
||||
return DataDecoder.DecodeNull(data);
|
||||
case NetworkDataType.Bool:
|
||||
return DataDecoder.DecodeBool(data);
|
||||
case NetworkDataType.Byte:
|
||||
return DataDecoder.DecodeByte(data);
|
||||
case NetworkDataType.Short:
|
||||
return DataDecoder.DecodeShort(data);
|
||||
case NetworkDataType.Int:
|
||||
return DataDecoder.DecodeInt(data);
|
||||
case NetworkDataType.Long:
|
||||
return DataDecoder.DecodeLong(data);
|
||||
case NetworkDataType.Float:
|
||||
return DataDecoder.DecodeFloat(data);
|
||||
case NetworkDataType.Double:
|
||||
return DataDecoder.DecodeDouble(data);
|
||||
case NetworkDataType.String:
|
||||
return DataDecoder.DecodeString(data);
|
||||
case NetworkDataType.BoolArray:
|
||||
return DataDecoder.DecodeBoolArray(data);
|
||||
case NetworkDataType.ByteArray:
|
||||
return DataDecoder.DecodeByteArray(data);
|
||||
case NetworkDataType.ShortArray:
|
||||
return DataDecoder.DecodeShortArray(data);
|
||||
case NetworkDataType.IntArray:
|
||||
return DataDecoder.DecodeIntArray(data);
|
||||
case NetworkDataType.LongArray:
|
||||
return DataDecoder.DecodeLongArray(data);
|
||||
case NetworkDataType.FloatArray:
|
||||
return DataDecoder.DecodeFloatArray(data);
|
||||
case NetworkDataType.DoubleArray:
|
||||
return DataDecoder.DecodeDoubleArray(data);
|
||||
case NetworkDataType.StringArray:
|
||||
return DataDecoder.DecodeStringArray(data);
|
||||
case NetworkDataType.NetworkArray:
|
||||
return DecodeNetworkArray(data);
|
||||
case NetworkDataType.NetworkObject:
|
||||
data.Seek(-1);
|
||||
return new DataWrapper(NetworkDataType.NetworkObject, new NetworkObject(data));
|
||||
default: throw new Exception("Invalid object");
|
||||
}
|
||||
}
|
||||
|
||||
private DataWrapper DecodeNetworkArray(NetworkData data) {
|
||||
NetworkArray array = new NetworkArray();
|
||||
short count = data.ReadShort();
|
||||
for (short i = 0; i < count; i++) {
|
||||
DataWrapper wrapper = DecodeObject(data);
|
||||
array.Add(wrapper);
|
||||
}
|
||||
return new DataWrapper(NetworkDataType.NetworkArray, array);
|
||||
}
|
||||
|
||||
public static NetworkObject WrapObject(byte c, short a, NetworkObject obj) {
|
||||
NetworkObject wrapper = new();
|
||||
wrapper.Add("c", c);
|
||||
wrapper.Add("a", a);
|
||||
wrapper.Add("p", obj);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
74
src/Data/NetworkPacket.cs
Normal file
74
src/Data/NetworkPacket.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
|
||||
namespace sodoffmmo.Data;
|
||||
public class NetworkPacket {
|
||||
|
||||
byte header;
|
||||
byte[] data;
|
||||
bool compressed = false;
|
||||
|
||||
public int Length {
|
||||
get {
|
||||
return data.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] SendData {
|
||||
get {
|
||||
NetworkData sendData = new();
|
||||
sendData.WriteValue(header);
|
||||
sendData.WriteValue((short)data.Length);
|
||||
sendData.WriteChunk(data);
|
||||
return sendData.Data;
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkPacket() {
|
||||
data = new byte[0];
|
||||
}
|
||||
|
||||
public NetworkPacket(NetworkData data, bool compressed = false) {
|
||||
header = 0x80;
|
||||
if (compressed) {
|
||||
header = 0xa0;
|
||||
this.compressed = true;
|
||||
}
|
||||
this.data = data.Data;
|
||||
}
|
||||
|
||||
public NetworkPacket(byte header, byte[] data) {
|
||||
this.header = header;
|
||||
this.data = data;
|
||||
if (header == 0xa0)
|
||||
compressed = true;
|
||||
}
|
||||
|
||||
public NetworkObject GetObject() {
|
||||
if (compressed)
|
||||
Decompress();
|
||||
|
||||
NetworkObject obj = new NetworkObject(data);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void Compress() {
|
||||
if (compressed)
|
||||
return;
|
||||
MemoryStream outStream = new();
|
||||
using (ZOutputStream zstream = new(outStream, 9)) {
|
||||
zstream.Write(data);
|
||||
zstream.Flush();
|
||||
}
|
||||
data = outStream.ToArray();
|
||||
header = 0xa0;
|
||||
}
|
||||
|
||||
public void Decompress() {
|
||||
MemoryStream outStream = new();
|
||||
using (ZOutputStream zstream = new(outStream)) {
|
||||
zstream.Write(data);
|
||||
zstream.Flush();
|
||||
}
|
||||
data = outStream.ToArray();
|
||||
}
|
||||
}
|
64
src/Data/PlayerData.cs
Normal file
64
src/Data/PlayerData.cs
Normal file
@ -0,0 +1,64 @@
|
||||
namespace sodoffmmo.Data;
|
||||
public class PlayerData {
|
||||
public int Id { get; set; } = -1;
|
||||
public double R { get; set; }
|
||||
public double R1 { get; set; }
|
||||
public double R2 { get; set; }
|
||||
public double R3 { get; set; }
|
||||
public string Fp { get; set; } = "";
|
||||
public double Mx { get; set; } = 6;
|
||||
public string Udt { get; set; } = "";
|
||||
public double P1 { get; set; }
|
||||
public double P2 { get; set; }
|
||||
public double P3 { get; set; }
|
||||
|
||||
public string Nt { get; set; } = "1.0";
|
||||
public int T { get; set; } = 0;
|
||||
public string J { get; set; } = "2";
|
||||
public int F { get; set; }
|
||||
public int Mbf { get; set; }
|
||||
public string Bu { get; set; } = "False";
|
||||
public string Uid { get; set; } = "";
|
||||
public string Pu { get; set; } = "";
|
||||
public string A { get; set; } = "";
|
||||
public string Ra { get; set; } = "";
|
||||
public string Cu { get; set; } = "-1";
|
||||
public string M { get; set; } = "False";
|
||||
public string L { get; set; } = "";
|
||||
|
||||
public NetworkArray GetNetworkData() {
|
||||
NetworkArray arr = new();
|
||||
arr.Add(Id);
|
||||
arr.Add(Uid);
|
||||
arr.Add((short)1);
|
||||
arr.Add((short)Id);
|
||||
|
||||
NetworkArray paramArr = new();
|
||||
paramArr.Add(NetworkArray.DoubleParam("R1", R1));
|
||||
paramArr.Add(NetworkArray.StringParam("FP", Fp));
|
||||
paramArr.Add(NetworkArray.DoubleParam("MX", Mx));
|
||||
paramArr.Add(NetworkArray.StringParam("UDT", Udt));
|
||||
paramArr.Add(NetworkArray.DoubleParam("P2", P2));
|
||||
paramArr.Add(NetworkArray.StringParam("NT", Nt));
|
||||
paramArr.Add(NetworkArray.IntParam("t", T));
|
||||
paramArr.Add(NetworkArray.StringParam("J", J));
|
||||
paramArr.Add(NetworkArray.IntParam("F", F));
|
||||
paramArr.Add(NetworkArray.IntParam("MBF", Mbf));
|
||||
paramArr.Add(NetworkArray.DoubleParam("R2", R2));
|
||||
paramArr.Add(NetworkArray.DoubleParam("R", R));
|
||||
paramArr.Add(NetworkArray.StringParam("BU", Bu));
|
||||
paramArr.Add(NetworkArray.DoubleParam("P1", P1));
|
||||
paramArr.Add(NetworkArray.StringParam("UID", Uid));
|
||||
paramArr.Add(NetworkArray.DoubleParam("R3", R3));
|
||||
paramArr.Add(NetworkArray.StringParam("PU", Pu));
|
||||
paramArr.Add(NetworkArray.StringParam("A", A));
|
||||
paramArr.Add(NetworkArray.StringParam("RA", Ra));
|
||||
paramArr.Add(NetworkArray.DoubleParam("P3", P3));
|
||||
paramArr.Add(NetworkArray.StringParam("CU", Cu));
|
||||
paramArr.Add(NetworkArray.StringParam("M", M));
|
||||
paramArr.Add(NetworkArray.StringParam("L", L));
|
||||
|
||||
arr.Add(paramArr);
|
||||
return arr;
|
||||
}
|
||||
}
|
5
src/Program.cs
Normal file
5
src/Program.cs
Normal file
@ -0,0 +1,5 @@
|
||||
using sodoffmmo;
|
||||
using System.Net;
|
||||
|
||||
Server server = new(IPAddress.Any, 9933);
|
||||
await server.Run();
|
77
src/Server.cs
Normal file
77
src/Server.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using sodoffmmo.Core;
|
||||
using sodoffmmo.Data;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace sodoffmmo;
|
||||
public class Server {
|
||||
|
||||
readonly int port;
|
||||
readonly IPAddress ipAddress;
|
||||
ModuleManager moduleManager = new();
|
||||
|
||||
public Server(IPAddress ipAdress, int port) {
|
||||
this.ipAddress = ipAdress;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public async Task Run() {
|
||||
moduleManager.RegisterModules();
|
||||
using Socket listener = new(ipAddress.AddressFamily,
|
||||
SocketType.Stream,
|
||||
ProtocolType.Tcp);
|
||||
|
||||
listener.Bind(new IPEndPoint(ipAddress, port));
|
||||
await Listen(listener);
|
||||
}
|
||||
|
||||
private async Task Listen(Socket listener) {
|
||||
Console.WriteLine($"MMO Server listening on port {port}");
|
||||
listener.Listen(100);
|
||||
while (true) {
|
||||
Socket handler = await listener.AcceptAsync();
|
||||
Console.WriteLine($"New connection from {((IPEndPoint)handler.RemoteEndPoint!).Address}");
|
||||
_ = HandleClient(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleClient(Socket handler) {
|
||||
Client client = new(handler);
|
||||
try {
|
||||
while (client.Connected) {
|
||||
await client.Receive();
|
||||
List<NetworkObject> networkObjects = new();
|
||||
while (client.TryGetNextPacket(out NetworkPacket packet))
|
||||
networkObjects.Add(packet.GetObject());
|
||||
|
||||
_ = Task.Run(() => HandleObjects(networkObjects, client));
|
||||
}
|
||||
} catch (SocketException) {
|
||||
client.Disconnect();
|
||||
} finally {
|
||||
try {
|
||||
client.LeaveRoom();
|
||||
} catch (Exception) { }
|
||||
Console.WriteLine("Socket disconnected IID: " + client.internalId);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleObjects(List<NetworkObject> networkObjects, Client client) {
|
||||
foreach (var obj in networkObjects) {
|
||||
try {
|
||||
short commandId = obj.Get<short>("a");
|
||||
ICommandHandler handler;
|
||||
if (commandId != 13) {
|
||||
Console.WriteLine($"System command: {commandId} IID: {client.internalId}");
|
||||
handler = moduleManager.GetCommandHandler(commandId);
|
||||
} else
|
||||
handler = moduleManager.GetCommandHandler(obj.Get<NetworkObject>("p").Get<string>("c"));
|
||||
handler.Handle(client, obj.Get<NetworkObject>("p"));
|
||||
} catch (Exception ex) {
|
||||
if (!ex.Message.Contains("ID 7")) // Missing command 7 flooding the log
|
||||
Console.WriteLine($"Exception IID: {client.internalId} - {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
src/sodoffmmo.csproj
Normal file
14
src/sodoffmmo.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ComponentAce.Compression.Libs.zlib" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user