Removed NioTSO client and server

- NioTSO client isn't needed because we're using RayLib
- Added FreeSO's API server to handle most backend operations
This commit is contained in:
Tony Bark 2024-05-01 02:55:43 -04:00
parent f12ba1502b
commit 22191ce648
591 changed files with 53264 additions and 3362 deletions

View file

@ -0,0 +1,36 @@
using System;
using Mina.Core.Buffer;
using FSO.Common.Serialization;
using FSO.Server.Protocol.Gluon.Packets;
namespace FSO.Server.Protocol.Gluon
{
public abstract class AbstractGluonPacket : IGluonPacket
{
public static IoBuffer Allocate(int size)
{
IoBuffer buffer = IoBuffer.Allocate(size);
buffer.Order = ByteOrder.BigEndian;
return buffer;
}
public abstract GluonPacketType GetPacketType();
public abstract void Deserialize(IoBuffer input, ISerializationContext context);
public abstract void Serialize(IoBuffer output, ISerializationContext context);
}
public abstract class AbstractGluonCallPacket : AbstractGluonPacket, IGluonCall
{
public Guid CallId { get; set; }
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutPascalString(CallId.ToString());
}
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
CallId = Guid.Parse(input.GetPascalString());
}
}
}

View file

@ -0,0 +1,107 @@
namespace FSO.Server.Protocol.Gluon
{
public enum GluonPacketType
{
AdvertiseCapacity,
TransferClaim,
TransferClaimResponse,
RequestLotClientTermination,
ShardShutdownRequest,
ShardShutdownCompleteResponse,
HealthPing,
HealthPingResponse,
RequestTask,
RequestTaskResponse,
NotifyLotRoommateChange,
MatchmakerNotify,
CityNotify,
TuningChanged,
CitySendMail,
Unknown
}
public static class GluonPacketTypeUtils
{
public static GluonPacketType FromPacketCode(ushort code)
{
switch (code)
{
case 0x0001:
return GluonPacketType.AdvertiseCapacity;
case 0x0002:
return GluonPacketType.TransferClaim;
case 0x0003:
return GluonPacketType.TransferClaimResponse;
case 0x0004:
return GluonPacketType.RequestLotClientTermination;
case 0x0005:
return GluonPacketType.ShardShutdownRequest;
case 0x0006:
return GluonPacketType.ShardShutdownCompleteResponse;
case 0x0007:
return GluonPacketType.HealthPing;
case 0x0008:
return GluonPacketType.HealthPingResponse;
case 0x0009:
return GluonPacketType.RequestTask;
case 0x0010:
return GluonPacketType.RequestTaskResponse;
case 0x0011:
return GluonPacketType.NotifyLotRoommateChange;
case 0x0012:
return GluonPacketType.MatchmakerNotify;
case 0x0013:
return GluonPacketType.CityNotify;
case 0x0014:
return GluonPacketType.TuningChanged;
case 0x0015:
return GluonPacketType.CitySendMail;
default:
return GluonPacketType.Unknown;
}
}
public static ushort GetPacketCode(this GluonPacketType type)
{
switch (type)
{
case GluonPacketType.AdvertiseCapacity:
return 0x0001;
case GluonPacketType.TransferClaim:
return 0x0002;
case GluonPacketType.TransferClaimResponse:
return 0x0003;
case GluonPacketType.RequestLotClientTermination:
return 0x0004;
case GluonPacketType.ShardShutdownRequest:
return 0x0005;
case GluonPacketType.ShardShutdownCompleteResponse:
return 0x0006;
case GluonPacketType.HealthPing:
return 0x0007;
case GluonPacketType.HealthPingResponse:
return 0x0008;
case GluonPacketType.RequestTask:
return 0x0009;
case GluonPacketType.RequestTaskResponse:
return 0x0010;
case GluonPacketType.NotifyLotRoommateChange:
return 0x0011;
case GluonPacketType.MatchmakerNotify:
return 0x0012;
case GluonPacketType.CityNotify:
return 0x0013;
case GluonPacketType.TuningChanged:
return 0x0014;
case GluonPacketType.CitySendMail:
return 0x0015;
}
return 0xFFFF;
}
}
}

View file

@ -0,0 +1,50 @@
using FSO.Server.Protocol.Gluon.Packets;
using System;
using System.Collections.Generic;
namespace FSO.Server.Protocol.Gluon
{
public class GluonPackets
{
public static Dictionary<ushort, Type> GLUON_PACKET_BY_TYPEID;
public static Type[] ELECTRON_PACKETS = new Type[] {
typeof(AdvertiseCapacity),
typeof(TransferClaim),
typeof(TransferClaimResponse),
typeof(RequestLotClientTermination),
typeof(ShardShutdownRequest),
typeof(ShardShutdownCompleteResponse),
typeof(HealthPing),
typeof(HealthPingResponse),
typeof(RequestTask),
typeof(RequestTaskResponse),
typeof(NotifyLotRoommateChange),
typeof(MatchmakerNotify),
typeof(CityNotify),
typeof(TuningChanged),
typeof(SendCityMail)
};
static GluonPackets()
{
GLUON_PACKET_BY_TYPEID = new Dictionary<ushort, Type>();
foreach (Type packetType in ELECTRON_PACKETS)
{
IGluonPacket packet = (IGluonPacket)Activator.CreateInstance(packetType);
GLUON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType);
}
}
public static Type GetByPacketCode(ushort code)
{
if (GLUON_PACKET_BY_TYPEID.ContainsKey(code))
{
return GLUON_PACKET_BY_TYPEID[code];
}
else
{
return null;
}
}
}
}

View file

@ -0,0 +1,9 @@
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Gluon
{
public interface IGluonPacket : IoBufferDeserializable, IoBufferSerializable
{
GluonPacketType GetPacketType();
}
}

View file

@ -0,0 +1,11 @@
namespace FSO.Server.Protocol.Gluon.Model
{
public enum ChangeType
{
REMOVE_ROOMMATE,
ADD_ROOMMATE,
BECOME_OWNER,
BECOME_OWNER_WITH_OBJECTS,
ROOMIE_INHERIT_OBJECTS_ONLY
}
}

View file

@ -0,0 +1,10 @@
namespace FSO.Server.Protocol.Gluon.Model
{
public enum ClaimAction
{
DEFAULT,
LOT_HOST,
LOT_CLEANUP
}
}

View file

@ -0,0 +1,8 @@
namespace FSO.Server.Protocol.Gluon.Model
{
public enum ClaimType
{
LOT,
AVATAR
}
}

View file

@ -0,0 +1,37 @@
using Mina.Core.Buffer;
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class AdvertiseCapacity : AbstractGluonPacket
{
public short MaxLots;
public short CurrentLots;
public byte CpuPercentAvg;
public long RamUsed;
public long RamAvaliable;
public override GluonPacketType GetPacketType()
{
return GluonPacketType.AdvertiseCapacity;
}
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
MaxLots = input.GetInt16();
CurrentLots = input.GetInt16();
CpuPercentAvg = input.Get();
RamUsed = input.GetInt64();
RamAvaliable = input.GetInt64();
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutInt16(MaxLots);
output.PutInt16(CurrentLots);
output.Put(CpuPercentAvg);
output.PutInt64(RamUsed);
output.PutInt64(RamAvaliable);
}
}
}

View file

@ -0,0 +1,45 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
// Task -> City notifications.
namespace FSO.Server.Protocol.Gluon.Packets
{
public class CityNotify : AbstractGluonPacket
{
public CityNotifyType Mode;
public uint Value;
public string Message = "";
public CityNotify() { }
public CityNotify(CityNotifyType mode)
{
Mode = mode;
}
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
Mode = input.GetEnum<CityNotifyType>();
Value = input.GetUInt32();
Message = input.GetPascalVLCString();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.CityNotify;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutEnum(Mode);
output.PutUInt32(Value);
output.PutPascalVLCString(Message);
}
}
public enum CityNotifyType : byte
{
NhoodUpdate = 1
}
}

View file

@ -0,0 +1,23 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class HealthPing : AbstractGluonCallPacket
{
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.HealthPing;
}
}
}

View file

@ -0,0 +1,27 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class HealthPingResponse : AbstractGluonCallPacket
{
public string PoolHash { get; set; }
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
PoolHash = input.GetPascalString();
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
output.PutPascalString(PoolHash);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.HealthPingResponse;
}
}
}

View file

@ -0,0 +1,9 @@
using System;
namespace FSO.Server.Protocol.Gluon.Packets
{
public interface IGluonCall
{
Guid CallId { get; set; }
}
}

View file

@ -0,0 +1,40 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
/// <summary>
/// Lot -> City server messages used to notify the matchmaker about some change to lot state.
/// (currently only when an avatar leaves a lot. this frees up a space for the matchmaker to shove someone else in)
/// </summary>
public class MatchmakerNotify : AbstractGluonPacket
{
public MatchmakerNotifyType Mode;
public uint LotID;
public uint AvatarID;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
Mode = input.GetEnum<MatchmakerNotifyType>();
LotID = input.GetUInt32();
AvatarID = input.GetUInt32();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.MatchmakerNotify;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutEnum(Mode);
output.PutUInt32(LotID);
output.PutUInt32(AvatarID);
}
}
public enum MatchmakerNotifyType : byte
{
RemoveAvatar = 1
}
}

View file

@ -0,0 +1,39 @@
using FSO.Common.Serialization;
using FSO.Server.Protocol.Gluon.Model;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
/// <summary>
/// A signal sent from the city server to notify a lot that an avatar's roommate status on that lot has changed.
/// May wish to change this to be more generic for further avatar related changes in future.
/// </summary>
public class NotifyLotRoommateChange : AbstractGluonPacket
{
public uint AvatarId;
public uint ReplaceId;
public int LotId;
public ChangeType Change;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
AvatarId = input.GetUInt32();
ReplaceId = input.GetUInt32();
LotId = input.GetInt32();
Change = input.GetEnum<ChangeType>();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.NotifyLotRoommateChange;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutUInt32(AvatarId);
output.PutUInt32(ReplaceId);
output.PutInt32(LotId);
output.PutEnum(Change);
}
}
}

View file

@ -0,0 +1,31 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class RequestLotClientTermination : AbstractGluonPacket
{
public uint AvatarId;
public int LotId;
public string FromOwner;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
AvatarId = input.GetUInt32();
LotId = input.GetInt32();
FromOwner = input.GetPascalString();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.RequestLotClientTermination;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutUInt32(AvatarId);
output.PutInt32(LotId);
output.PutPascalString(FromOwner);
}
}
}

View file

@ -0,0 +1,34 @@
using System.Text;
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class RequestTask : AbstractGluonCallPacket
{
public string TaskType { get; set; }
public string ParameterJson { get; set; }
public int ShardId { get; set; }
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
TaskType = input.GetPascalString();
ShardId = input.GetInt32();
ParameterJson = input.GetString(Encoding.UTF8);
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
output.PutPascalString(TaskType);
output.PutInt32(ShardId);
output.PutString(ParameterJson, Encoding.UTF8);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.RequestTask;
}
}
}

View file

@ -0,0 +1,27 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class RequestTaskResponse : AbstractGluonCallPacket
{
public int TaskId;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
TaskId = input.GetInt32();
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
output.PutInt32(TaskId);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.RequestTaskResponse;
}
}
}

View file

@ -0,0 +1,58 @@
using FSO.Common.Serialization;
using FSO.Files.Formats.tsodata;
using Mina.Core.Buffer;
using System.Collections.Generic;
using System.IO;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class SendCityMail : AbstractGluonCallPacket
{
public List<MessageItem> Items { get; set; }
public SendCityMail() { }
public SendCityMail(List<MessageItem> items) {
Items = items;
}
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
var itemCount = input.GetInt32();
var dataSize = input.GetInt32();
var data = input.GetSlice(dataSize).GetBytes();
using (var mem = new MemoryStream(data)) {
Items = new List<MessageItem>();
for (int i = 0; i < itemCount; i++)
{
var message = new MessageItem();
message.Read(mem);
Items.Add(message);
}
}
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
byte[] data = null;
using (var mem = new MemoryStream())
{
foreach (var item in Items)
{
item.Save(mem);
}
data = mem.ToArray();
}
output.PutInt32(Items.Count);
output.PutInt32(data.Length);
output.Put(data);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.CitySendMail;
}
}
}

View file

@ -0,0 +1,25 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class ShardShutdownCompleteResponse : AbstractGluonPacket
{
public uint ShardId;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
ShardId = input.GetUInt32();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.ShardShutdownCompleteResponse;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutUInt32(ShardId);
}
}
}

View file

@ -0,0 +1,29 @@
using FSO.Common.Serialization;
using FSO.Server.Common;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class ShardShutdownRequest : AbstractGluonPacket
{
public uint ShardId;
public ShutdownType Type;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
ShardId = input.GetUInt32();
Type = input.GetEnum<ShutdownType>();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.ShardShutdownRequest;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutUInt32(ShardId);
output.PutEnum(Type);
}
}
}

View file

@ -0,0 +1,41 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
using FSO.Server.Protocol.Gluon.Model;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class TransferClaim : AbstractGluonPacket
{
public ClaimType Type;
public ClaimAction Action;
public int EntityId;
public uint ClaimId;
public uint SpecialId; //job lot info
public string FromOwner;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
Type = input.GetEnum<ClaimType>();
Action = input.GetEnum<ClaimAction>();
EntityId = input.GetInt32();
ClaimId = input.GetUInt32();
SpecialId = input.GetUInt32();
FromOwner = input.GetPascalString();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.TransferClaim;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutEnum(Type);
output.PutEnum(Action);
output.PutInt32(EntityId);
output.PutUInt32(ClaimId);
output.PutUInt32(SpecialId);
output.PutPascalString(FromOwner);
}
}
}

View file

@ -0,0 +1,45 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
using FSO.Server.Protocol.Gluon.Model;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class TransferClaimResponse : AbstractGluonPacket
{
public TransferClaimResponseStatus Status;
public ClaimType Type;
public int EntityId;
public uint ClaimId;
public string NewOwner;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
Status = input.GetEnum<TransferClaimResponseStatus>();
Type = input.GetEnum<ClaimType>();
EntityId = input.GetInt32();
ClaimId = input.GetUInt32();
NewOwner = input.GetPascalString();
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.TransferClaimResponse;
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutEnum(Status);
output.PutEnum(Type);
output.PutInt32(EntityId);
output.PutUInt32(ClaimId);
output.PutPascalString(NewOwner);
}
}
public enum TransferClaimResponseStatus
{
ACCEPTED,
REJECTED,
CLAIM_NOT_FOUND
}
}

View file

@ -0,0 +1,27 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Gluon.Packets
{
public class TuningChanged : AbstractGluonCallPacket
{
public bool UpdateInstantly;
public override void Deserialize(IoBuffer input, ISerializationContext context)
{
base.Deserialize(input, context);
UpdateInstantly = input.GetBool();
}
public override void Serialize(IoBuffer output, ISerializationContext context)
{
base.Serialize(output, context);
output.PutBool(UpdateInstantly);
}
public override GluonPacketType GetPacketType()
{
return GluonPacketType.TuningChanged;
}
}
}