chore: reformatting
All checks were successful
Build, Package and Push Images / preprocess (push) Successful in 2s
Build, Package and Push Images / build (push) Successful in 25s
Build, Package and Push Images / sbom-scan (push) Successful in 49s
Build, Package and Push Images / container-build (push) Successful in 2m11s
Build, Package and Push Images / sonarqube (push) Successful in 2m12s
Build, Package and Push Images / container-sbom-scan (push) Successful in 39s
All checks were successful
Build, Package and Push Images / preprocess (push) Successful in 2s
Build, Package and Push Images / build (push) Successful in 25s
Build, Package and Push Images / sbom-scan (push) Successful in 49s
Build, Package and Push Images / container-build (push) Successful in 2m11s
Build, Package and Push Images / sonarqube (push) Successful in 2m12s
Build, Package and Push Images / container-sbom-scan (push) Successful in 39s
This commit is contained in:
parent
db63e581e5
commit
9f3007b10e
40 changed files with 416 additions and 379 deletions
|
@ -12,11 +12,6 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: actionlint
|
- id: actionlint
|
||||||
additional_dependencies: [pyflakes>=3.0.1, shellcheck-py>=0.9.0.5]
|
additional_dependencies: [pyflakes>=3.0.1, shellcheck-py>=0.9.0.5]
|
||||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
|
||||||
rev: v2.11.0
|
|
||||||
hooks:
|
|
||||||
- id: pretty-format-yaml
|
|
||||||
args: [--autofix, --indent, '2']
|
|
||||||
- repo: https://github.com/hadolint/hadolint
|
- repo: https://github.com/hadolint/hadolint
|
||||||
rev: v2.12.0
|
rev: v2.12.0
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.10"/>
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.110">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.110">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
namespace Benchmarks;
|
using System.Buffers.Binary;
|
||||||
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using BenchmarkDotNet.Order;
|
using BenchmarkDotNet.Order;
|
||||||
|
|
||||||
|
namespace Benchmarks;
|
||||||
|
|
||||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||||
[Config(typeof(GenericConfig))]
|
[Config(typeof(GenericConfig))]
|
||||||
public class BinaryConversionBenchmarks
|
public class BinaryConversionBenchmarks
|
||||||
|
@ -15,48 +16,53 @@ public class BinaryConversionBenchmarks
|
||||||
[GlobalSetup]
|
[GlobalSetup]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
this._data = RandomNumberGenerator.GetBytes(4000);
|
_data = RandomNumberGenerator.GetBytes(4000);
|
||||||
this._offset = RandomNumberGenerator.GetInt32(0, 3500);
|
_offset = RandomNumberGenerator.GetInt32(0, 3500);
|
||||||
this._writeBuffer = RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);
|
_writeBuffer = RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public short BitConverterParseTest() => BitConverter.ToInt16(this._data, this._offset);
|
public short BitConverterParseTest()
|
||||||
|
{
|
||||||
|
return BitConverter.ToInt16(_data, _offset);
|
||||||
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public short BinaryReader()
|
public short BinaryReader()
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream(this._data);
|
using var ms = new MemoryStream(_data);
|
||||||
using var reader = new BinaryReader(ms);
|
using var reader = new BinaryReader(ms);
|
||||||
reader.BaseStream.Position = this._offset;
|
reader.BaseStream.Position = _offset;
|
||||||
return reader.ReadInt16();
|
return reader.ReadInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public short BinaryPrimitivesRead() =>
|
public short BinaryPrimitivesRead()
|
||||||
System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian(
|
{
|
||||||
new ArraySegment<byte>(this._data, this._offset, sizeof(short)));
|
return BinaryPrimitives.ReadInt16LittleEndian(
|
||||||
|
new ArraySegment<byte>(_data, _offset, sizeof(short)));
|
||||||
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void BinaryPrimitivesWrite()
|
public void BinaryPrimitivesWrite()
|
||||||
{
|
{
|
||||||
System.Buffers.Binary.BinaryPrimitives.WriteInt32LittleEndian(this._data.AsSpan(_offset, 4),
|
BinaryPrimitives.WriteInt32LittleEndian(_data.AsSpan(_offset, 4),
|
||||||
this._writeBuffer);
|
_writeBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void BitConverterCopy()
|
public void BitConverterCopy()
|
||||||
{
|
{
|
||||||
BitConverter.GetBytes(this._writeBuffer).CopyTo(this._data, this._offset);
|
BitConverter.GetBytes(_writeBuffer).CopyTo(_data, _offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void BitConverterAssignment()
|
public void BitConverterAssignment()
|
||||||
{
|
{
|
||||||
var bytes = BitConverter.GetBytes(this._writeBuffer);
|
var bytes = BitConverter.GetBytes(_writeBuffer);
|
||||||
this._data[this._offset] = bytes[0];
|
_data[_offset] = bytes[0];
|
||||||
this._data[this._offset + 1] = bytes[1];
|
_data[_offset + 1] = bytes[1];
|
||||||
this._data[this._offset + 2] = bytes[2];
|
_data[_offset + 2] = bytes[2];
|
||||||
this._data[this._offset + 3] = bytes[3];
|
_data[_offset + 3] = bytes[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
namespace Benchmarks;
|
|
||||||
|
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using BenchmarkDotNet.Order;
|
using BenchmarkDotNet.Order;
|
||||||
|
|
||||||
|
namespace Benchmarks;
|
||||||
|
|
||||||
[Config(typeof(GenericConfig))]
|
[Config(typeof(GenericConfig))]
|
||||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||||
public class DataCacheBenchmark
|
public class DataCacheBenchmark
|
||||||
{
|
{
|
||||||
[Params(1000, 100000, 1000000)] public int N;
|
|
||||||
private HashSet<int> _hashSet;
|
|
||||||
private Dictionary<int, int> _dictionary;
|
|
||||||
private ConcurrentDictionary<int, int> _concurrentDictionary;
|
private ConcurrentDictionary<int, int> _concurrentDictionary;
|
||||||
|
private Dictionary<int, int> _dictionary;
|
||||||
|
private HashSet<int> _hashSet;
|
||||||
private ImmutableHashSet<int> _immutableHashSet;
|
private ImmutableHashSet<int> _immutableHashSet;
|
||||||
|
[Params(1000, 100000, 1000000)] public int N;
|
||||||
|
|
||||||
[GlobalSetup]
|
[GlobalSetup]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using Wonderking.Packets;
|
|
||||||
|
|
||||||
namespace Server;
|
|
||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using MassTransit.Mediator;
|
using MassTransit.Mediator;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NetCoreServer;
|
using NetCoreServer;
|
||||||
using Packets;
|
using Server.Packets;
|
||||||
|
using Wonderking.Packets;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
public class AuthSession : TcpSession
|
public class AuthSession : TcpSession
|
||||||
{
|
{
|
||||||
|
@ -17,22 +16,22 @@ public class AuthSession : TcpSession
|
||||||
public AuthSession(TcpServer
|
public AuthSession(TcpServer
|
||||||
server, IMediator mediator, ILogger<AuthSession> logger) : base(server)
|
server, IMediator mediator, ILogger<AuthSession> logger) : base(server)
|
||||||
{
|
{
|
||||||
this._mediator = mediator;
|
_mediator = mediator;
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid AccountId { get; set; }
|
public Guid AccountId { get; set; }
|
||||||
|
|
||||||
public override long Send(byte[] buffer)
|
public override long Send(byte[] buffer)
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
|
_logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
|
||||||
return base.Send(buffer);
|
return base.Send(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendAsync(IPacket packet)
|
public Task SendAsync(IPacket packet)
|
||||||
{
|
{
|
||||||
var type = packet.GetType();
|
var type = packet.GetType();
|
||||||
this._logger.LogInformation("Packet of type {Type} is being serialized", type.Name);
|
_logger.LogInformation("Packet of type {Type} is being serialized", type.Name);
|
||||||
var packetIdAttribute = type.GetCustomAttribute<PacketIdAttribute>();
|
var packetIdAttribute = type.GetCustomAttribute<PacketIdAttribute>();
|
||||||
if (packetIdAttribute == null)
|
if (packetIdAttribute == null)
|
||||||
{
|
{
|
||||||
|
@ -60,41 +59,41 @@ public class AuthSession : TcpSession
|
||||||
buffer[2 + i] = bytesOfOpcode[i];
|
buffer[2 + i] = bytesOfOpcode[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._logger.LogInformation("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
|
_logger.LogInformation("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
|
||||||
this._logger.LogInformation("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
|
_logger.LogInformation("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
|
||||||
|
|
||||||
this.SendAsync(buffer);
|
SendAsync(buffer);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||||
{
|
{
|
||||||
this._logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset);
|
_logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset);
|
||||||
Span<byte> decryptedBuffer = new byte[size];
|
Span<byte> decryptedBuffer = new byte[size];
|
||||||
|
|
||||||
// xor every value after the first 8 bytes
|
// xor every value after the first 8 bytes
|
||||||
var dataBuffer = Decrypt(new ArraySegment<byte>(buffer, 8, (int)size - 8).ToArray());
|
var dataBuffer = Decrypt(new ArraySegment<byte>(buffer, 8, (int)size - 8).ToArray());
|
||||||
|
|
||||||
this._logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0));
|
_logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0));
|
||||||
|
|
||||||
var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2);
|
var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2);
|
||||||
|
|
||||||
this._logger.LogDebug("Packet Op Code: {OpCode}", opCode);
|
_logger.LogDebug("Packet Op Code: {OpCode}", opCode);
|
||||||
this._logger.LogDebug("Some Value: {RandomValue}", buffer[4]);
|
_logger.LogDebug("Some Value: {RandomValue}", buffer[4]);
|
||||||
|
|
||||||
var clientAliveTime = BitConverter.ToUInt16(buffer.ToArray(), 5);
|
var clientAliveTime = BitConverter.ToUInt16(buffer.ToArray(), 5);
|
||||||
|
|
||||||
this._logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime);
|
_logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime);
|
||||||
this._logger.LogDebug("Might be a flag: {Flag}", buffer[7]);
|
_logger.LogDebug("Might be a flag: {Flag}", buffer[7]);
|
||||||
|
|
||||||
this._logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray()));
|
_logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray()));
|
||||||
|
|
||||||
var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[7],
|
var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[7],
|
||||||
buffer[4], this.Id, this);
|
buffer[4], Id, this);
|
||||||
|
|
||||||
_ = this._mediator.Send(rawPacket);
|
_ = _mediator.Send(rawPacket);
|
||||||
|
|
||||||
this._logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString());
|
_logger.LogInformation("Connection from: {@RemoteEndpoint}", Socket.RemoteEndPoint?.ToString());
|
||||||
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
|
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
namespace Server;
|
|
||||||
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MassTransit.Mediator;
|
using MassTransit.Mediator;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NetCoreServer;
|
using NetCoreServer;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
public class ChannelSession : TcpSession
|
public class ChannelSession : TcpSession
|
||||||
{
|
{
|
||||||
private static readonly byte[] _key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 }
|
private static readonly byte[] _key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 }
|
||||||
|
@ -24,8 +24,8 @@ public class ChannelSession : TcpSession
|
||||||
|
|
||||||
public ChannelSession(TcpServer server, IMediator mediator, ILogger<ChannelSession> logger) : base(server)
|
public ChannelSession(TcpServer server, IMediator mediator, ILogger<ChannelSession> logger) : base(server)
|
||||||
{
|
{
|
||||||
this._mediator = mediator;
|
_mediator = mediator;
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
var aes = Aes.Create();
|
var aes = Aes.Create();
|
||||||
aes.Key = _key;
|
aes.Key = _key;
|
||||||
aes.IV = _iv;
|
aes.IV = _iv;
|
||||||
|
@ -34,8 +34,8 @@ public class ChannelSession : TcpSession
|
||||||
aes.Mode = CipherMode.ECB;
|
aes.Mode = CipherMode.ECB;
|
||||||
#pragma warning restore SEC0026
|
#pragma warning restore SEC0026
|
||||||
|
|
||||||
this._decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
_decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||||
this._encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
_encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||||
|
@ -43,12 +43,12 @@ public class ChannelSession : TcpSession
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var ms = new MemoryStream(Decrypt(buffer)))
|
using (var ms = new MemoryStream(Decrypt(buffer)))
|
||||||
using (var cs = new CryptoStream(ms, this._decryptor, CryptoStreamMode.Read))
|
using (var cs = new CryptoStream(ms, _decryptor, CryptoStreamMode.Read))
|
||||||
{
|
{
|
||||||
var amountOfReadBytes = cs.Read(buffer);
|
var amountOfReadBytes = cs.Read(buffer);
|
||||||
if (amountOfReadBytes != buffer.Length)
|
if (amountOfReadBytes != buffer.Length)
|
||||||
{
|
{
|
||||||
this._logger.LogError("Amount of read bytes is not equal to buffer length.");
|
_logger.LogError("Amount of read bytes is not equal to buffer length.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ public class ChannelSession : TcpSession
|
||||||
}
|
}
|
||||||
catch (CryptographicException ex)
|
catch (CryptographicException ex)
|
||||||
{
|
{
|
||||||
this._logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
|
_logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
|
||||||
this._logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
|
_logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
namespace Server.Consumers;
|
|
||||||
|
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Packets;
|
using Server.Packets;
|
||||||
using Services;
|
using Server.Services;
|
||||||
|
|
||||||
|
namespace Server.Consumers;
|
||||||
|
|
||||||
public class PacketConsumer : IConsumer<RawPacket>
|
public class PacketConsumer : IConsumer<RawPacket>
|
||||||
{
|
{
|
||||||
private readonly PacketDistributorService _distributorService;
|
private readonly PacketDistributorService _distributorService;
|
||||||
|
|
||||||
public PacketConsumer(PacketDistributorService distributorService) => this._distributorService = distributorService;
|
public PacketConsumer(PacketDistributorService distributorService)
|
||||||
|
{
|
||||||
|
_distributorService = distributorService;
|
||||||
|
}
|
||||||
|
|
||||||
public Task Consume(ConsumeContext<RawPacket> context)
|
public Task Consume(ConsumeContext<RawPacket> context)
|
||||||
{
|
{
|
||||||
this._distributorService.AddPacket(context.Message);
|
_distributorService.AddPacket(context.Message);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,17 @@ using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Server.DB.Documents;
|
namespace Server.DB.Documents;
|
||||||
|
|
||||||
[Index(nameof(Username), IsUnique = true), Index(nameof(Id), IsUnique = true)]
|
[Index(nameof(Username), IsUnique = true)]
|
||||||
|
[Index(nameof(Id), IsUnique = true)]
|
||||||
public class Account
|
public class Account
|
||||||
{
|
{
|
||||||
public Account(string username, byte[] password, string email, byte permissionLevel, byte[] salt)
|
public Account(string username, byte[] password, string email, byte permissionLevel, byte[] salt)
|
||||||
{
|
{
|
||||||
this.Username = username;
|
Username = username;
|
||||||
this.Password = password;
|
Password = password;
|
||||||
this.Email = email;
|
Email = email;
|
||||||
this.PermissionLevel = permissionLevel;
|
PermissionLevel = permissionLevel;
|
||||||
this.Salt = salt;
|
Salt = salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Key]
|
[Key]
|
||||||
|
|
|
@ -6,7 +6,8 @@ using Wonderking.Packets.Outgoing.Data;
|
||||||
|
|
||||||
namespace Server.DB.Documents;
|
namespace Server.DB.Documents;
|
||||||
|
|
||||||
[Index(nameof(Name), IsUnique = true), Index(nameof(Id), IsUnique = true)]
|
[Index(nameof(Name), IsUnique = true)]
|
||||||
|
[Index(nameof(Id), IsUnique = true)]
|
||||||
public class Character
|
public class Character
|
||||||
{
|
{
|
||||||
public virtual Account Account { get; set; }
|
public virtual Account Account { get; set; }
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Server.DB.Documents;
|
||||||
|
|
||||||
namespace Server.DB;
|
namespace Server.DB;
|
||||||
|
|
||||||
using Documents;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
public class WonderkingContext : DbContext
|
public class WonderkingContext : DbContext
|
||||||
{
|
{
|
||||||
public WonderkingContext([NotNull] DbContextOptions options) : base(options)
|
public WonderkingContext([NotNull] DbContextOptions options) : base(options)
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NetCoreServer;
|
||||||
|
using Server.DB;
|
||||||
using Server.DB.Documents;
|
using Server.DB.Documents;
|
||||||
using Wonderking.Packets.Incoming;
|
using Wonderking.Packets.Incoming;
|
||||||
using Wonderking.Packets.Outgoing;
|
using Wonderking.Packets.Outgoing;
|
||||||
|
@ -6,11 +10,6 @@ using Wonderking.Packets.Outgoing.Data;
|
||||||
|
|
||||||
namespace Server.PacketHandlers;
|
namespace Server.PacketHandlers;
|
||||||
|
|
||||||
using DB;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using NetCoreServer;
|
|
||||||
|
|
||||||
public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
||||||
{
|
{
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
@ -20,9 +19,9 @@ public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
||||||
public ChannelSelectionHandler(IConfiguration configuration, ILogger<ChannelSelectionHandler> logger,
|
public ChannelSelectionHandler(IConfiguration configuration, ILogger<ChannelSelectionHandler> logger,
|
||||||
WonderkingContext wonderkingContext)
|
WonderkingContext wonderkingContext)
|
||||||
{
|
{
|
||||||
this._configuration = configuration;
|
_configuration = configuration;
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
this._wonderkingContext = wonderkingContext;
|
_wonderkingContext = wonderkingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleAsync(ChannelSelectionPacket packet, TcpSession session)
|
public async Task HandleAsync(ChannelSelectionPacket packet, TcpSession session)
|
||||||
|
@ -31,7 +30,7 @@ public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
||||||
ChannelSelectionResponsePacket responsePacket;
|
ChannelSelectionResponsePacket responsePacket;
|
||||||
var guildNameResponsePacket = new CharacterSelectionSetGuildNamePacket { GuildNames = Array.Empty<string>() };
|
var guildNameResponsePacket = new CharacterSelectionSetGuildNamePacket { GuildNames = Array.Empty<string>() };
|
||||||
|
|
||||||
var account = await this._wonderkingContext.Accounts
|
var account = await _wonderkingContext.Accounts
|
||||||
.FirstOrDefaultAsync(a => a.Id == authSession.AccountId).ConfigureAwait(true);
|
.FirstOrDefaultAsync(a => a.Id == authSession.AccountId).ConfigureAwait(true);
|
||||||
if (account != null && account.Characters.Count > 0)
|
if (account != null && account.Characters.Count > 0)
|
||||||
{
|
{
|
||||||
|
@ -59,9 +58,9 @@ public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
||||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
||||||
EquippedCashItems = GetItemIDsByInventoryTab(c.InventoryItems
|
EquippedCashItems = GetItemIDsByInventoryTab(c.InventoryItems
|
||||||
.Where(item => item.InventoryTab == InventoryTab.WornCashEquipment)
|
.Where(item => item.InventoryTab == InventoryTab.WornCashEquipment)
|
||||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray())
|
||||||
})
|
})
|
||||||
.ToArrayAsync().ConfigureAwait(true),
|
.ToArrayAsync().ConfigureAwait(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
guildNameResponsePacket.GuildNames = await _wonderkingContext.Characters
|
guildNameResponsePacket.GuildNames = await _wonderkingContext.Characters
|
||||||
|
|
|
@ -13,9 +13,9 @@ namespace Server.PacketHandlers;
|
||||||
|
|
||||||
public class CharacterCreationHandler : IPacketHandler<CharacterCreationPacket>
|
public class CharacterCreationHandler : IPacketHandler<CharacterCreationPacket>
|
||||||
{
|
{
|
||||||
private readonly WonderkingContext _wonderkingContext;
|
|
||||||
private readonly ItemObjectPoolService _itemObjectPoolService;
|
|
||||||
private readonly CharacterStatsMappingConfiguration _characterStatsMapping;
|
private readonly CharacterStatsMappingConfiguration _characterStatsMapping;
|
||||||
|
private readonly ItemObjectPoolService _itemObjectPoolService;
|
||||||
|
private readonly WonderkingContext _wonderkingContext;
|
||||||
|
|
||||||
public CharacterCreationHandler(WonderkingContext wonderkingContext, ItemObjectPoolService itemObjectPoolService,
|
public CharacterCreationHandler(WonderkingContext wonderkingContext, ItemObjectPoolService itemObjectPoolService,
|
||||||
CharacterStatsMappingConfiguration characterStatsMappingConfiguration)
|
CharacterStatsMappingConfiguration characterStatsMappingConfiguration)
|
||||||
|
@ -62,7 +62,7 @@ public class CharacterCreationHandler : IPacketHandler<CharacterCreationPacket>
|
||||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
||||||
packet.Shirt + 49)),
|
packet.Shirt + 49)),
|
||||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
||||||
packet.Pants + 58)),
|
packet.Pants + 58))
|
||||||
];
|
];
|
||||||
|
|
||||||
var calculateCurrentMana = CalculateCurrentMana(1, firstJobConfig);
|
var calculateCurrentMana = CalculateCurrentMana(1, firstJobConfig);
|
||||||
|
@ -109,13 +109,13 @@ public class CharacterCreationHandler : IPacketHandler<CharacterCreationPacket>
|
||||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
||||||
EquippedCashItems = GetItemIDsByInventoryTab(c.InventoryItems
|
EquippedCashItems = GetItemIDsByInventoryTab(c.InventoryItems
|
||||||
.Where(item => item.InventoryTab == InventoryTab.WornCashEquipment)
|
.Where(item => item.InventoryTab == InventoryTab.WornCashEquipment)
|
||||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray()),
|
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).ToArray())
|
||||||
}).FirstAsync().ConfigureAwait(true);
|
}).FirstAsync().ConfigureAwait(true);
|
||||||
await authSession.SendAsync(new CharacterCreationResponsePacket
|
await authSession.SendAsync(new CharacterCreationResponsePacket
|
||||||
{
|
{
|
||||||
Character = character,
|
Character = character,
|
||||||
Slot = packet.Slot,
|
Slot = packet.Slot,
|
||||||
isDuplicate = false,
|
isDuplicate = false
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using NetCoreServer;
|
||||||
using Wonderking.Packets;
|
using Wonderking.Packets;
|
||||||
|
|
||||||
namespace Server.PacketHandlers;
|
namespace Server.PacketHandlers;
|
||||||
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using NetCoreServer;
|
|
||||||
|
|
||||||
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
|
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
|
||||||
public interface IPacketHandler<in T> where T : IPacket
|
public interface IPacketHandler<in T> where T : IPacket
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Konscious.Security.Cryptography;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NetCoreServer;
|
||||||
|
using Server.DB;
|
||||||
|
using Server.DB.Documents;
|
||||||
using Server.LoggerMessages;
|
using Server.LoggerMessages;
|
||||||
using Wonderking.Packets.Incoming;
|
using Wonderking.Packets.Incoming;
|
||||||
using Wonderking.Packets.Outgoing;
|
using Wonderking.Packets.Outgoing;
|
||||||
|
@ -7,13 +13,6 @@ using Wonderking.Packets.Outgoing.Data;
|
||||||
|
|
||||||
namespace Server.PacketHandlers;
|
namespace Server.PacketHandlers;
|
||||||
|
|
||||||
using DB;
|
|
||||||
using DB.Documents;
|
|
||||||
using Konscious.Security.Cryptography;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using NetCoreServer;
|
|
||||||
|
|
||||||
public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||||
{
|
{
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
@ -22,9 +21,55 @@ public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||||
|
|
||||||
public LoginHandler(ILogger<LoginHandler> logger, WonderkingContext wonderkingContext, IConfiguration configuration)
|
public LoginHandler(ILogger<LoginHandler> logger, WonderkingContext wonderkingContext, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
this._wonderkingContext = wonderkingContext;
|
_wonderkingContext = wonderkingContext;
|
||||||
this._configuration = configuration;
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
|
||||||
|
{
|
||||||
|
LoginResponseReason loginResponseReason;
|
||||||
|
_logger.LoginData(packet.Username, packet.Password);
|
||||||
|
var account = _wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
|
||||||
|
|
||||||
|
if (account == null)
|
||||||
|
{
|
||||||
|
if (_configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
|
||||||
|
{
|
||||||
|
loginResponseReason = await CreateAccountOnLoginAsync(packet.Username, packet.Password)
|
||||||
|
.ConfigureAwait(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.RequestedAccountDoesNotExist(packet.Username);
|
||||||
|
loginResponseReason = LoginResponseReason.AccountDoesNotExit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var salt = account.Salt;
|
||||||
|
var tempPasswordBytes = await GetPasswordHashAsync(packet.Password, salt, account.Id)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
loginResponseReason = tempPasswordBytes.SequenceEqual(account.Password)
|
||||||
|
? LoginResponseReason.Ok
|
||||||
|
: LoginResponseReason.WrongPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loginResponsePacket = new LoginResponsePacket
|
||||||
|
{
|
||||||
|
ResponseReason = loginResponseReason,
|
||||||
|
ChannelData = new[] { new ServerChannelData { ChannelId = 0, LoadPercentage = 0, ServerId = 0 } },
|
||||||
|
UnknownFlag = 1,
|
||||||
|
IsGameMaster = true
|
||||||
|
};
|
||||||
|
var authSession = session as AuthSession;
|
||||||
|
if (account != null && authSession != null)
|
||||||
|
{
|
||||||
|
authSession.AccountId = account.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("LoginResponsePacket: {@LoginResponsePacket}", loginResponsePacket);
|
||||||
|
authSession?.SendAsync(loginResponsePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task<byte[]> GetPasswordHashAsync(string password, byte[] salt, Guid userId)
|
private static Task<byte[]> GetPasswordHashAsync(string password, byte[] salt, Guid userId)
|
||||||
|
@ -53,16 +98,16 @@ public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||||
{
|
{
|
||||||
var salt = RandomNumberGenerator.GetBytes(16);
|
var salt = RandomNumberGenerator.GetBytes(16);
|
||||||
var finalAccount =
|
var finalAccount =
|
||||||
await this._wonderkingContext.Accounts.AddAsync(new Account(username,
|
await _wonderkingContext.Accounts.AddAsync(new Account(username,
|
||||||
Array.Empty<byte>(), "",
|
Array.Empty<byte>(), "",
|
||||||
0, salt)).ConfigureAwait(true);
|
0, salt)).ConfigureAwait(true);
|
||||||
await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
|
await _wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
|
||||||
finalAccount.Entity.Password =
|
finalAccount.Entity.Password =
|
||||||
await LoginHandler.GetPasswordHashAsync(password, salt, finalAccount.Entity.Id)
|
await GetPasswordHashAsync(password, salt, finalAccount.Entity.Id)
|
||||||
.ConfigureAwait(true);
|
.ConfigureAwait(true);
|
||||||
this._wonderkingContext.Accounts.Update(finalAccount.Entity);
|
_wonderkingContext.Accounts.Update(finalAccount.Entity);
|
||||||
loginResponseReason = LoginResponseReason.Ok;
|
loginResponseReason = LoginResponseReason.Ok;
|
||||||
await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
|
await _wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
|
||||||
|
|
||||||
await transaction.CommitAsync().ConfigureAwait(true);
|
await transaction.CommitAsync().ConfigureAwait(true);
|
||||||
}
|
}
|
||||||
|
@ -75,50 +120,4 @@ public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||||
|
|
||||||
return loginResponseReason;
|
return loginResponseReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
|
|
||||||
{
|
|
||||||
LoginResponseReason loginResponseReason;
|
|
||||||
this._logger.LoginData(packet.Username, packet.Password);
|
|
||||||
var account = this._wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
|
|
||||||
|
|
||||||
if (account == null)
|
|
||||||
{
|
|
||||||
if (this._configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
|
|
||||||
{
|
|
||||||
loginResponseReason = await CreateAccountOnLoginAsync(packet.Username, packet.Password)
|
|
||||||
.ConfigureAwait(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this._logger.RequestedAccountDoesNotExist(packet.Username);
|
|
||||||
loginResponseReason = LoginResponseReason.AccountDoesNotExit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var salt = account.Salt;
|
|
||||||
var tempPasswordBytes = await LoginHandler.GetPasswordHashAsync(packet.Password, salt, account.Id)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
loginResponseReason = tempPasswordBytes.SequenceEqual(account.Password)
|
|
||||||
? LoginResponseReason.Ok
|
|
||||||
: LoginResponseReason.WrongPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
var loginResponsePacket = new LoginResponsePacket
|
|
||||||
{
|
|
||||||
ResponseReason = loginResponseReason,
|
|
||||||
ChannelData = new[] { new ServerChannelData { ChannelId = 0, LoadPercentage = 0, ServerId = 0 } },
|
|
||||||
UnknownFlag = 1,
|
|
||||||
IsGameMaster = true
|
|
||||||
};
|
|
||||||
var sess = session as AuthSession;
|
|
||||||
if (account != null && sess != null)
|
|
||||||
{
|
|
||||||
sess.AccountId = account.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("LoginResponsePacket: {@LoginResponsePacket}", loginResponsePacket);
|
|
||||||
sess?.SendAsync(loginResponsePacket);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
|
using MassTransit;
|
||||||
using Wonderking.Packets;
|
using Wonderking.Packets;
|
||||||
|
|
||||||
namespace Server.Packets;
|
namespace Server.Packets;
|
||||||
|
|
||||||
using MassTransit;
|
|
||||||
|
|
||||||
[MessageUrn("packets")]
|
[MessageUrn("packets")]
|
||||||
public class RawPacket
|
public class RawPacket
|
||||||
{
|
{
|
||||||
public RawPacket(OperationCode operationCode, byte[] messageBody, uint aliveTime, byte unknownValue2,
|
public RawPacket(OperationCode operationCode, byte[] messageBody, uint aliveTime, byte unknownValue2,
|
||||||
byte unknownValue, Guid sessionId, AuthSession session)
|
byte unknownValue, Guid sessionId, AuthSession session)
|
||||||
{
|
{
|
||||||
this.MessageBody = messageBody;
|
MessageBody = messageBody;
|
||||||
this.UnknownValue2 = unknownValue2;
|
UnknownValue2 = unknownValue2;
|
||||||
this.UnknownValue = unknownValue;
|
UnknownValue = unknownValue;
|
||||||
this.SessionId = sessionId;
|
SessionId = sessionId;
|
||||||
this.Session = session;
|
Session = session;
|
||||||
this.OperationCode = operationCode;
|
OperationCode = operationCode;
|
||||||
/*
|
/*
|
||||||
* 20s = 5
|
* 20s = 5
|
||||||
* 15s = 4
|
* 15s = 4
|
||||||
* 10s = 3
|
* 10s = 3
|
||||||
* client alive time * 5s => uptime
|
* client alive time * 5s => uptime
|
||||||
*/
|
*/
|
||||||
this.ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
|
ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationCode OperationCode { get; }
|
public OperationCode OperationCode { get; }
|
||||||
|
|
|
@ -41,16 +41,16 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="DotNext" Version="4.15.2" />
|
<PackageReference Include="DotNext" Version="4.15.2"/>
|
||||||
<PackageReference Include="DotNext.IO" Version="4.15.0"/>
|
<PackageReference Include="DotNext.IO" Version="4.15.0"/>
|
||||||
<PackageReference Include="DotNext.Metaprogramming" Version="4.15.0"/>
|
<PackageReference Include="DotNext.Metaprogramming" Version="4.15.0"/>
|
||||||
<PackageReference Include="DotNext.Reflection" Version="4.9.0"/>
|
<PackageReference Include="DotNext.Reflection" Version="4.9.0"/>
|
||||||
<PackageReference Include="DotNext.Threading" Version="4.15.2" />
|
<PackageReference Include="DotNext.Threading" Version="4.15.2"/>
|
||||||
<PackageReference Include="DotNext.Unsafe" Version="4.14.0"/>
|
<PackageReference Include="DotNext.Unsafe" Version="4.14.0"/>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/>
|
||||||
<PackageReference Include="JetBrains.ExternalAnnotations" Version="10.2.135" />
|
<PackageReference Include="JetBrains.ExternalAnnotations" Version="10.2.135"/>
|
||||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.0"/>
|
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.0"/>
|
||||||
<PackageReference Include="MassTransit" Version="8.1.2" />
|
<PackageReference Include="MassTransit" Version="8.1.2"/>
|
||||||
<PackageReference Include="MassTransit.Analyzers" Version="8.1.2">
|
<PackageReference Include="MassTransit.Analyzers" Version="8.1.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
@ -66,31 +66,31 @@
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0"/>
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0"/>
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="8.0.0"/>
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
|
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="NetCoreServer" Version="7.0.0" />
|
<PackageReference Include="NetCoreServer" Version="7.0.0"/>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2"/>
|
||||||
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.10.4539">
|
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.10.4539">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0"/>
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0"/>
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Server.Services;
|
||||||
|
|
||||||
public class ItemObjectPoolService : IHostedService
|
public class ItemObjectPoolService : IHostedService
|
||||||
{
|
{
|
||||||
readonly ConcurrentDictionary<uint, ItemObject> _itemObjectPool;
|
private readonly ConcurrentDictionary<uint, ItemObject> _itemObjectPool;
|
||||||
private readonly ItemReader _itemReader;
|
private readonly ItemReader _itemReader;
|
||||||
private readonly ILogger<ItemObjectPoolService> _logger;
|
private readonly ILogger<ItemObjectPoolService> _logger;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public class ItemObjectPoolService : IHostedService
|
||||||
|
|
||||||
public InventoryItem GetBaseInventoryItem(ushort itemId, ushort count = 1, bool isWorn = false)
|
public InventoryItem GetBaseInventoryItem(ushort itemId, ushort count = 1, bool isWorn = false)
|
||||||
{
|
{
|
||||||
var item = this.GetItem(itemId);
|
var item = GetItem(itemId);
|
||||||
return new InventoryItem
|
return new InventoryItem
|
||||||
{
|
{
|
||||||
ItemId = itemId,
|
ItemId = itemId,
|
||||||
|
|
|
@ -1,38 +1,41 @@
|
||||||
using Server.LoggerMessages;
|
|
||||||
using Wonderking.Packets;
|
|
||||||
|
|
||||||
namespace Server.Services;
|
|
||||||
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using DotNext.Collections.Generic;
|
using DotNext.Collections.Generic;
|
||||||
|
using DotNext.Linq.Expressions;
|
||||||
|
using DotNext.Metaprogramming;
|
||||||
using MassTransit.Internals;
|
using MassTransit.Internals;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.VisualBasic.CompilerServices;
|
using Microsoft.VisualBasic.CompilerServices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PacketHandlers;
|
using Server.LoggerMessages;
|
||||||
using Packets;
|
using Server.PacketHandlers;
|
||||||
using static DotNext.Linq.Expressions.ExpressionBuilder;
|
using Server.Packets;
|
||||||
using static DotNext.Metaprogramming.CodeGenerator;
|
using Wonderking.Packets;
|
||||||
|
|
||||||
|
namespace Server.Services;
|
||||||
|
|
||||||
|
using static CodeGenerator;
|
||||||
|
using static ExpressionBuilder;
|
||||||
|
|
||||||
public class PacketDistributorService : IHostedService
|
public class PacketDistributorService : IHostedService
|
||||||
{
|
{
|
||||||
private readonly ConcurrentQueue<RawPacket> _concurrentQueue;
|
private readonly ConcurrentQueue<RawPacket> _concurrentQueue;
|
||||||
|
|
||||||
|
private readonly ILogger<PacketDistributorService> _logger;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
private ImmutableDictionary<OperationCode,
|
private ImmutableDictionary<OperationCode,
|
||||||
Func<byte[], IPacket>> _deserializationMap;
|
Func<byte[], IPacket>> _deserializationMap;
|
||||||
|
|
||||||
private readonly ILogger<PacketDistributorService> _logger;
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private ConcurrentDictionary<OperationCode, object> _packetHandlersInstantiation;
|
private ConcurrentDictionary<OperationCode, object> _packetHandlersInstantiation;
|
||||||
|
|
||||||
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
|
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
this._concurrentQueue = new ConcurrentQueue<RawPacket>();
|
_concurrentQueue = new ConcurrentQueue<RawPacket>();
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,15 +45,15 @@ public class PacketDistributorService : IHostedService
|
||||||
new Dictionary<OperationCode, Func<byte[], IPacket>>();
|
new Dictionary<OperationCode, Func<byte[], IPacket>>();
|
||||||
|
|
||||||
var wonderkingAssembly = Assembly.GetAssembly(typeof(IPacket));
|
var wonderkingAssembly = Assembly.GetAssembly(typeof(IPacket));
|
||||||
var packetsTypes = this.GetPacketsWithId(wonderkingAssembly);
|
var packetsTypes = GetPacketsWithId(wonderkingAssembly);
|
||||||
var packetHandlers = this.GetAllPacketHandlersWithId(Assembly.GetExecutingAssembly());
|
var packetHandlers = GetAllPacketHandlersWithId(Assembly.GetExecutingAssembly());
|
||||||
this._packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, object>();
|
_packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, object>();
|
||||||
packetHandlers.ForEach(x =>
|
packetHandlers.ForEach(x =>
|
||||||
{
|
{
|
||||||
var packetHandler =
|
var packetHandler =
|
||||||
ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider,
|
ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider,
|
||||||
x.Value);
|
x.Value);
|
||||||
this._packetHandlersInstantiation.TryAdd(x.Key, packetHandler);
|
_packetHandlersInstantiation.TryAdd(x.Key, packetHandler);
|
||||||
});
|
});
|
||||||
foreach (var packetsType in packetsTypes)
|
foreach (var packetsType in packetsTypes)
|
||||||
{
|
{
|
||||||
|
@ -69,11 +72,14 @@ public class PacketDistributorService : IHostedService
|
||||||
tempDeserializationMap.Add(packetsType.Key, lambda);
|
tempDeserializationMap.Add(packetsType.Key, lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._deserializationMap = tempDeserializationMap.ToImmutableDictionary();
|
_deserializationMap = tempDeserializationMap.ToImmutableDictionary();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private Dictionary<OperationCode, Type> GetPacketsWithId(Assembly executingAssembly)
|
private Dictionary<OperationCode, Type> GetPacketsWithId(Assembly executingAssembly)
|
||||||
{
|
{
|
||||||
|
@ -87,11 +93,11 @@ public class PacketDistributorService : IHostedService
|
||||||
if (packetsWithId is not { Count: 0 })
|
if (packetsWithId is not { Count: 0 })
|
||||||
{
|
{
|
||||||
packetsWithId.AsParallel()
|
packetsWithId.AsParallel()
|
||||||
.ForAll(packet => this._logger.PacketWithIdAdded(packet.Key, packet.Value.FullName));
|
.ForAll(packet => _logger.PacketWithIdAdded(packet.Key, packet.Value.FullName));
|
||||||
return packetsWithId;
|
return packetsWithId;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._logger.NoPacketsFound();
|
_logger.NoPacketsFound();
|
||||||
throw new IncompleteInitialization();
|
throw new IncompleteInitialization();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,44 +125,44 @@ public class PacketDistributorService : IHostedService
|
||||||
if (packetHandlersWithId is not { Count: 0 })
|
if (packetHandlersWithId is not { Count: 0 })
|
||||||
{
|
{
|
||||||
packetHandlersWithId.AsParallel().ForAll(packetHandler =>
|
packetHandlersWithId.AsParallel().ForAll(packetHandler =>
|
||||||
this._logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName));
|
_logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName));
|
||||||
return packetHandlersWithId;
|
return packetHandlersWithId;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._logger.NoPacketHandlersFound();
|
_logger.NoPacketHandlersFound();
|
||||||
throw new IncompleteInitialization();
|
throw new IncompleteInitialization();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPacket(RawPacket rawPacket)
|
public void AddPacket(RawPacket rawPacket)
|
||||||
{
|
{
|
||||||
this._concurrentQueue.Enqueue(rawPacket);
|
_concurrentQueue.Enqueue(rawPacket);
|
||||||
this.DequeueRawPacket();
|
DequeueRawPacket();
|
||||||
this._logger.PacketReceived(rawPacket.OperationCode);
|
_logger.PacketReceived(rawPacket.OperationCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DequeueRawPacket()
|
private void DequeueRawPacket()
|
||||||
{
|
{
|
||||||
if (this._concurrentQueue.TryDequeue(out var item))
|
if (_concurrentQueue.TryDequeue(out var item))
|
||||||
{
|
{
|
||||||
ThreadPool.QueueUserWorkItem(this.InvokePacketHandler, item, true);
|
ThreadPool.QueueUserWorkItem(InvokePacketHandler, item, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InvokePacketHandler(RawPacket item)
|
private void InvokePacketHandler(RawPacket item)
|
||||||
{
|
{
|
||||||
this._logger.PacketDequeued(item.Session.Id, item.OperationCode);
|
_logger.PacketDequeued(item.Session.Id, item.OperationCode);
|
||||||
if (!this._deserializationMap.TryGetValue(item.OperationCode, out var value))
|
if (!_deserializationMap.TryGetValue(item.OperationCode, out var value))
|
||||||
{
|
{
|
||||||
this._logger.PacketTypeNotFound(item.OperationCode);
|
_logger.PacketTypeNotFound(item.OperationCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packet = value(item.MessageBody);
|
var packet = value(item.MessageBody);
|
||||||
this._logger.PacketData(JsonConvert.SerializeObject(packet));
|
_logger.PacketData(JsonConvert.SerializeObject(packet));
|
||||||
this._packetHandlersInstantiation[item.OperationCode].GetType()
|
_packetHandlersInstantiation[item.OperationCode].GetType()
|
||||||
.GetMethod(nameof(IPacketHandler<IPacket>.HandleAsync))
|
.GetMethod(nameof(IPacketHandler<IPacket>.HandleAsync))
|
||||||
?.Invoke(this._packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session });
|
?.Invoke(_packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session });
|
||||||
|
|
||||||
this._logger.PacketFinished(item.Session.Id, item.OperationCode);
|
_logger.PacketFinished(item.Session.Id, item.OperationCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
namespace Server.Services;
|
|
||||||
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -7,6 +5,8 @@ using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NetCoreServer;
|
using NetCoreServer;
|
||||||
|
|
||||||
|
namespace Server.Services;
|
||||||
|
|
||||||
public class WonderkingAuthServer : TcpServer, IHostedService
|
public class WonderkingAuthServer : TcpServer, IHostedService
|
||||||
{
|
{
|
||||||
private readonly ILogger<WonderkingAuthServer> _logger;
|
private readonly ILogger<WonderkingAuthServer> _logger;
|
||||||
|
@ -15,61 +15,66 @@ public class WonderkingAuthServer : TcpServer, IHostedService
|
||||||
public WonderkingAuthServer(IPAddress address, int port, ILogger<WonderkingAuthServer> logger,
|
public WonderkingAuthServer(IPAddress address, int port, ILogger<WonderkingAuthServer> logger,
|
||||||
IServiceProvider serviceProvider) : base(address, port)
|
IServiceProvider serviceProvider) : base(address, port)
|
||||||
{
|
{
|
||||||
this._logger = logger;
|
_logger = logger;
|
||||||
this._serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.Start();
|
Start();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.DisconnectAll();
|
DisconnectAll();
|
||||||
this.Stop();
|
Stop();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TcpSession CreateSession() =>
|
protected override TcpSession CreateSession()
|
||||||
ActivatorUtilities.CreateInstance<AuthSession>(this._serviceProvider, this);
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance<AuthSession>(_serviceProvider, this);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnStarting()
|
protected override void OnStarting()
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Starting");
|
_logger.LogInformation("Starting");
|
||||||
base.OnStarting();
|
base.OnStarting();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStarted()
|
protected override void OnStarted()
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Started");
|
_logger.LogInformation("Started");
|
||||||
base.OnStarted();
|
base.OnStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStopping()
|
protected override void OnStopping()
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Stopping");
|
_logger.LogInformation("Stopping");
|
||||||
base.OnStopping();
|
base.OnStopping();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStopped()
|
protected override void OnStopped()
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Stopped");
|
_logger.LogInformation("Stopped");
|
||||||
base.OnStopped();
|
base.OnStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnConnected(TcpSession session)
|
protected override void OnConnected(TcpSession session)
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Client connected {Session}", session.Id);
|
_logger.LogInformation("Client connected {Session}", session.Id);
|
||||||
base.OnConnected(session);
|
base.OnConnected(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisconnected(TcpSession session)
|
protected override void OnDisconnected(TcpSession session)
|
||||||
{
|
{
|
||||||
this._logger.LogInformation("Client disconnected {Session}", session.Id);
|
_logger.LogInformation("Client disconnected {Session}", session.Id);
|
||||||
base.OnDisconnected(session);
|
base.OnDisconnected(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnError(SocketError error) => this._logger.LogError("An error has occured {Error}", error);
|
protected override void OnError(SocketError error)
|
||||||
|
{
|
||||||
|
_logger.LogError("An error has occured {Error}", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
"Testing": {
|
"Testing": {
|
||||||
"CreateAccountOnLogin": true
|
"CreateAccountOnLogin": true
|
||||||
},
|
},
|
||||||
"Game":{
|
"Game": {
|
||||||
"Data":{
|
"Data": {
|
||||||
"Path": "../wk-data/"
|
"Path": "../wk-data/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,3 @@ public struct CraftMaterial
|
||||||
public uint ID;
|
public uint ID;
|
||||||
public uint Amount;
|
public uint Amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,51 +5,67 @@ namespace Wonderking.Game.Data.Item;
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 64)]
|
[StructLayout(LayoutKind.Explicit, Size = 64)]
|
||||||
public struct ElementalStats
|
public struct ElementalStats
|
||||||
{
|
{
|
||||||
[FieldOffset(0), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(0)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MinimumFireDamage;
|
public int MinimumFireDamage;
|
||||||
|
|
||||||
[FieldOffset(4), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(4)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MinimumWaterDamage;
|
public int MinimumWaterDamage;
|
||||||
|
|
||||||
[FieldOffset(8), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(8)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MinimumDarkDamage;
|
public int MinimumDarkDamage;
|
||||||
|
|
||||||
[FieldOffset(12), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(12)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MinimumHolyDamage;
|
public int MinimumHolyDamage;
|
||||||
|
|
||||||
[FieldOffset(16), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(16)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MaximumFireDamage;
|
public int MaximumFireDamage;
|
||||||
|
|
||||||
[FieldOffset(20), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(20)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MaximumWaterDamage;
|
public int MaximumWaterDamage;
|
||||||
|
|
||||||
[FieldOffset(24), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(24)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MaximumDarkDamage;
|
public int MaximumDarkDamage;
|
||||||
|
|
||||||
[FieldOffset(28), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(28)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int MaximumHolyDamage;
|
public int MaximumHolyDamage;
|
||||||
|
|
||||||
[FieldOffset(32), MarshalAs(UnmanagedType.U4)]
|
[FieldOffset(32)]
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
public uint ElementFire;
|
public uint ElementFire;
|
||||||
|
|
||||||
[FieldOffset(36), MarshalAs(UnmanagedType.U4)]
|
[FieldOffset(36)]
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
public uint ElementWater;
|
public uint ElementWater;
|
||||||
|
|
||||||
[FieldOffset(40), MarshalAs(UnmanagedType.U4)]
|
[FieldOffset(40)]
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
public uint ElementDark;
|
public uint ElementDark;
|
||||||
|
|
||||||
[FieldOffset(44), MarshalAs(UnmanagedType.U4)]
|
[FieldOffset(44)]
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
public uint ElementHoly;
|
public uint ElementHoly;
|
||||||
|
|
||||||
[FieldOffset(48), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(48)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int FireResistance;
|
public int FireResistance;
|
||||||
|
|
||||||
[FieldOffset(52), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(52)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int WaterResistance;
|
public int WaterResistance;
|
||||||
|
|
||||||
[FieldOffset(56), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(56)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int DarkResistance;
|
public int DarkResistance;
|
||||||
|
|
||||||
[FieldOffset(60), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(60)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int HolyResistance;
|
public int HolyResistance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,27 @@ namespace Wonderking.Game.Data.Item;
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 24)]
|
[StructLayout(LayoutKind.Explicit, Size = 24)]
|
||||||
public struct Stats
|
public struct Stats
|
||||||
{
|
{
|
||||||
[FieldOffset(0), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(0)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Strength;
|
public int Strength;
|
||||||
|
|
||||||
[FieldOffset(4), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(4)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Dexterity;
|
public int Dexterity;
|
||||||
|
|
||||||
[FieldOffset(8), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(8)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Intelligence;
|
public int Intelligence;
|
||||||
|
|
||||||
[FieldOffset(12), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(12)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Vitality;
|
public int Vitality;
|
||||||
|
|
||||||
[FieldOffset(16), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(16)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Luck;
|
public int Luck;
|
||||||
|
|
||||||
[FieldOffset(20), MarshalAs(UnmanagedType.I4)]
|
[FieldOffset(20)]
|
||||||
|
[MarshalAs(UnmanagedType.I4)]
|
||||||
public int Wisdom;
|
public int Wisdom;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,11 @@ namespace Wonderking.Game;
|
||||||
|
|
||||||
public abstract class DataReader<T>
|
public abstract class DataReader<T>
|
||||||
{
|
{
|
||||||
|
private readonly string _datFileName;
|
||||||
|
|
||||||
|
private readonly byte _xorKey;
|
||||||
|
protected readonly ushort SizeOfEntry;
|
||||||
|
|
||||||
protected DataReader(string path)
|
protected DataReader(string path)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
|
@ -15,6 +20,8 @@ public abstract class DataReader<T>
|
||||||
|
|
||||||
private protected string Path { get; init; }
|
private protected string Path { get; init; }
|
||||||
|
|
||||||
|
protected byte[] DatFileContent { get; }
|
||||||
|
|
||||||
public abstract uint GetAmountOfEntries();
|
public abstract uint GetAmountOfEntries();
|
||||||
public abstract T GetEntry(uint entryId);
|
public abstract T GetEntry(uint entryId);
|
||||||
|
|
||||||
|
@ -36,20 +43,14 @@ public abstract class DataReader<T>
|
||||||
throw new NotSupportedException("XorKey is null");
|
throw new NotSupportedException("XorKey is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly byte _xorKey;
|
|
||||||
protected readonly ushort SizeOfEntry;
|
|
||||||
private readonly string _datFileName;
|
|
||||||
|
|
||||||
protected byte[] DatFileContent { get; }
|
|
||||||
|
|
||||||
private Span<byte> GetDatFileContent(string path)
|
private Span<byte> GetDatFileContent(string path)
|
||||||
{
|
{
|
||||||
var fileData = File.ReadAllBytes(path + this._datFileName);
|
var fileData = File.ReadAllBytes(path + _datFileName);
|
||||||
var data = new byte[fileData.Length];
|
var data = new byte[fileData.Length];
|
||||||
|
|
||||||
for (var i = 0; i < fileData.Length; i++)
|
for (var i = 0; i < fileData.Length; i++)
|
||||||
{
|
{
|
||||||
data[i] = (byte)(fileData[i] ^ this._xorKey);
|
data[i] = (byte)(fileData[i] ^ _xorKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -4,8 +4,7 @@ namespace Wonderking.Game.Mapping;
|
||||||
|
|
||||||
public class Item
|
public class Item
|
||||||
{
|
{
|
||||||
[JsonPropertyName("id")]
|
[JsonPropertyName("id")] public ushort Id { get; set; }
|
||||||
public ushort Id { get; set; }
|
|
||||||
[JsonPropertyName("quantity")]
|
[JsonPropertyName("quantity")] public ushort Quantity { get; set; }
|
||||||
public ushort Quantity { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,9 @@ namespace Wonderking.Game.Mapping;
|
||||||
|
|
||||||
public class JobSpecificMapping
|
public class JobSpecificMapping
|
||||||
{
|
{
|
||||||
[JsonPropertyName("items")]
|
[JsonPropertyName("items")] public ICollection<Item> Items { get; set; }
|
||||||
public ICollection<Item> Items { get; set; }
|
|
||||||
[JsonPropertyName("baseStats")]
|
[JsonPropertyName("baseStats")] public BaseStats BaseStats { get; set; }
|
||||||
public BaseStats BaseStats { get; set; }
|
|
||||||
[JsonPropertyName("dynamicStats")]
|
[JsonPropertyName("dynamicStats")] public DynamicStats DynamicStats { get; set; }
|
||||||
public DynamicStats DynamicStats { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/* Nicht gemergte Änderung aus Projekt "Wonderking(net7.0)"
|
/* Nicht gemergte Änderung aus Projekt "Wonderking(net7.0)"
|
||||||
Vor:
|
Vor:
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
|
@ -9,14 +9,14 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
{
|
{
|
||||||
public override uint GetAmountOfEntries()
|
public override uint GetAmountOfEntries()
|
||||||
{
|
{
|
||||||
return (uint)((this.DatFileContent.Length - 9) / this.SizeOfEntry);
|
return (uint)((DatFileContent.Length - 9) / SizeOfEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ItemObject GetEntry(uint entryId)
|
public override ItemObject GetEntry(uint entryId)
|
||||||
{
|
{
|
||||||
var item = new ItemObject();
|
var item = new ItemObject();
|
||||||
var arraySegment = new ArraySegment<byte>(DatFileContent,
|
var arraySegment = new ArraySegment<byte>(DatFileContent,
|
||||||
9 + (int)entryId * this.SizeOfEntry, this.SizeOfEntry);
|
9 + (int)entryId * SizeOfEntry, SizeOfEntry);
|
||||||
var data = new Span<byte>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
|
var data = new Span<byte>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
|
||||||
item.ItemID = BitConverter.ToUInt32(data.Slice(0, 4)); // 0 -> 4
|
item.ItemID = BitConverter.ToUInt32(data.Slice(0, 4)); // 0 -> 4
|
||||||
item.Disabled = BitConverter.ToBoolean(data.Slice(4, 4)); // 4 -> 8
|
item.Disabled = BitConverter.ToBoolean(data.Slice(4, 4)); // 4 -> 8
|
||||||
|
@ -49,7 +49,7 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
Intelligence = BitConverter.ToInt32(data.Slice(124, 4)), // 124 -> 128
|
Intelligence = BitConverter.ToInt32(data.Slice(124, 4)), // 124 -> 128
|
||||||
Vitality = BitConverter.ToInt32(data.Slice(128, 4)), // 128 -> 132
|
Vitality = BitConverter.ToInt32(data.Slice(128, 4)), // 128 -> 132
|
||||||
Luck = BitConverter.ToInt32(data.Slice(132, 4)), // 132 -> 136
|
Luck = BitConverter.ToInt32(data.Slice(132, 4)), // 132 -> 136
|
||||||
Wisdom = BitConverter.ToInt32(data.Slice(136, 4)), // 136 -> 140
|
Wisdom = BitConverter.ToInt32(data.Slice(136, 4)) // 136 -> 140
|
||||||
}; // 116 -> 140
|
}; // 116 -> 140
|
||||||
item.ElementalStats = new ElementalStats
|
item.ElementalStats = new ElementalStats
|
||||||
{
|
{
|
||||||
|
@ -68,7 +68,7 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
FireResistance = BitConverter.ToInt32(data.Slice(188, 4)), // 188 -> 192
|
FireResistance = BitConverter.ToInt32(data.Slice(188, 4)), // 188 -> 192
|
||||||
WaterResistance = BitConverter.ToInt32(data.Slice(192, 4)), // 192 -> 196
|
WaterResistance = BitConverter.ToInt32(data.Slice(192, 4)), // 192 -> 196
|
||||||
DarkResistance = BitConverter.ToInt32(data.Slice(196, 4)), // 196 -> 200
|
DarkResistance = BitConverter.ToInt32(data.Slice(196, 4)), // 196 -> 200
|
||||||
HolyResistance = BitConverter.ToInt32(data.Slice(200, 4)), // 200 -> 204
|
HolyResistance = BitConverter.ToInt32(data.Slice(200, 4)) // 200 -> 204
|
||||||
}; // 140 -> 204
|
}; // 140 -> 204
|
||||||
item.R7C = data.Slice(204, 4).ToArray(); // 204 -> 208
|
item.R7C = data.Slice(204, 4).ToArray(); // 204 -> 208
|
||||||
item.R8C = data.Slice(208, 8).ToArray(); // 208 -> 216
|
item.R8C = data.Slice(208, 8).ToArray(); // 208 -> 216
|
||||||
|
@ -118,7 +118,7 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
{
|
{
|
||||||
ID = BitConverter.ToUInt32(data.Slice(332, 4)), // 332 -> 336
|
ID = BitConverter.ToUInt32(data.Slice(332, 4)), // 332 -> 336
|
||||||
Amount = BitConverter.ToUInt32(data.Slice(348, 4)) // 348 -> 352
|
Amount = BitConverter.ToUInt32(data.Slice(348, 4)) // 348 -> 352
|
||||||
},
|
}
|
||||||
}; // 320 -> 352
|
}; // 320 -> 352
|
||||||
item.CraftResultAmount = BitConverter.ToUInt32(data.Slice(352, 4)); // 352 -> 356
|
item.CraftResultAmount = BitConverter.ToUInt32(data.Slice(352, 4)); // 352 -> 356
|
||||||
item.R14C = data.Slice(356, 4).ToArray(); // 356 -> 360
|
item.R14C = data.Slice(356, 4).ToArray(); // 356 -> 360
|
||||||
|
@ -141,7 +141,7 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
BitConverter.ToUInt32(data.Slice(800, 4)), // 800 -> 804
|
BitConverter.ToUInt32(data.Slice(800, 4)), // 800 -> 804
|
||||||
BitConverter.ToUInt32(data.Slice(804, 4)), // 804 -> 808
|
BitConverter.ToUInt32(data.Slice(804, 4)), // 804 -> 808
|
||||||
BitConverter.ToUInt32(data.Slice(808, 4)), // 808 -> 812
|
BitConverter.ToUInt32(data.Slice(808, 4)), // 808 -> 812
|
||||||
BitConverter.ToUInt32(data.Slice(812, 4)), // 812 -> 816
|
BitConverter.ToUInt32(data.Slice(812, 4)) // 812 -> 816
|
||||||
}; // 796 -> 816
|
}; // 796 -> 816
|
||||||
item.SetID = BitConverter.ToUInt32(data.Slice(816, 4)); // 816 -> 820
|
item.SetID = BitConverter.ToUInt32(data.Slice(816, 4)); // 816 -> 820
|
||||||
item.Options = new ItemOptions
|
item.Options = new ItemOptions
|
||||||
|
@ -151,9 +151,9 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
BitConverter.ToUInt32(data.Slice(824, 4)), // 824 -> 828
|
BitConverter.ToUInt32(data.Slice(824, 4)), // 824 -> 828
|
||||||
BitConverter.ToUInt32(data.Slice(828, 4)), // 828 -> 832
|
BitConverter.ToUInt32(data.Slice(828, 4)), // 828 -> 832
|
||||||
BitConverter.ToUInt32(data.Slice(832, 4)), // 832 -> 836
|
BitConverter.ToUInt32(data.Slice(832, 4)), // 832 -> 836
|
||||||
BitConverter.ToUInt32(data.Slice(836, 4)), // 836 -> 840
|
BitConverter.ToUInt32(data.Slice(836, 4)) // 836 -> 840
|
||||||
},
|
},
|
||||||
OptionAvailable = BitConverter.ToBoolean(data.Slice(820, 4)), // 820 -> 824
|
OptionAvailable = BitConverter.ToBoolean(data.Slice(820, 4)) // 820 -> 824
|
||||||
}; // 820 -> 840
|
}; // 820 -> 840
|
||||||
item.Unknown19 = data.Slice(840, 23).ToArray(); // 840 -> 863
|
item.Unknown19 = data.Slice(840, 23).ToArray(); // 840 -> 863
|
||||||
item.PetID = data[863]; // 863 -> 864
|
item.PetID = data[863]; // 863 -> 864
|
||||||
|
@ -186,7 +186,7 @@ public class ItemReader(string path) : DataReader<ItemObject>(path)
|
||||||
{
|
{
|
||||||
ID = BitConverter.ToInt16(data.Slice(906, 2)), // 906 -> 908
|
ID = BitConverter.ToInt16(data.Slice(906, 2)), // 906 -> 908
|
||||||
ObtainChance = BitConverter.ToSingle(data.Slice(924, 4)) // 924 -> 928
|
ObtainChance = BitConverter.ToSingle(data.Slice(924, 4)) // 924 -> 928
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
item.MinimumLevelRequirement = data[928]; // 928 -> 929
|
item.MinimumLevelRequirement = data[928]; // 928 -> 929
|
||||||
item.Unknown21_2 = data.Slice(929, 3).ToArray(); // 929 -> 932
|
item.Unknown21_2 = data.Slice(929, 3).ToArray(); // 929 -> 932
|
||||||
|
|
|
@ -6,20 +6,20 @@ public static class ItemReaderExtensions
|
||||||
{
|
{
|
||||||
public static Stats ReadStats(this BinaryReader reader)
|
public static Stats ReadStats(this BinaryReader reader)
|
||||||
{
|
{
|
||||||
return new Stats()
|
return new Stats
|
||||||
{
|
{
|
||||||
Strength = reader.ReadInt32(), //125
|
Strength = reader.ReadInt32(), //125
|
||||||
Dexterity = reader.ReadInt32(), //129
|
Dexterity = reader.ReadInt32(), //129
|
||||||
Intelligence = reader.ReadInt32(), //133
|
Intelligence = reader.ReadInt32(), //133
|
||||||
Vitality = reader.ReadInt32(), //137
|
Vitality = reader.ReadInt32(), //137
|
||||||
Luck = reader.ReadInt32(), //141
|
Luck = reader.ReadInt32(), //141
|
||||||
Wisdom = reader.ReadInt32(), //145
|
Wisdom = reader.ReadInt32() //145
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ElementalStats ReadElementalStats(this BinaryReader reader)
|
public static ElementalStats ReadElementalStats(this BinaryReader reader)
|
||||||
{
|
{
|
||||||
return new ElementalStats()
|
return new ElementalStats
|
||||||
{
|
{
|
||||||
MinimumFireDamage = reader.ReadInt32(), //149
|
MinimumFireDamage = reader.ReadInt32(), //149
|
||||||
MinimumWaterDamage = reader.ReadInt32(), //153
|
MinimumWaterDamage = reader.ReadInt32(), //153
|
||||||
|
@ -36,7 +36,7 @@ public static class ItemReaderExtensions
|
||||||
FireResistance = reader.ReadInt32(), //197
|
FireResistance = reader.ReadInt32(), //197
|
||||||
WaterResistance = reader.ReadInt32(), //201
|
WaterResistance = reader.ReadInt32(), //201
|
||||||
DarkResistance = reader.ReadInt32(), //205
|
DarkResistance = reader.ReadInt32(), //205
|
||||||
HolyResistance = reader.ReadInt32(), //209
|
HolyResistance = reader.ReadInt32() //209
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,12 @@ public class ChannelSelectionPacket : IPacket
|
||||||
|
|
||||||
public void Deserialize(byte[] data)
|
public void Deserialize(byte[] data)
|
||||||
{
|
{
|
||||||
this.ServerId = BitConverter.ToUInt16(data, 0);
|
ServerId = BitConverter.ToUInt16(data, 0);
|
||||||
this.ChannelId = BitConverter.ToUInt16(data, 2);
|
ChannelId = BitConverter.ToUInt16(data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize() => throw new NotSupportedException();
|
public byte[] Serialize()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,22 +11,22 @@ public class LoginInfoPacket : IPacket
|
||||||
|
|
||||||
public void Deserialize(byte[] data)
|
public void Deserialize(byte[] data)
|
||||||
{
|
{
|
||||||
this.Username = Encoding.ASCII.GetString(data, 0, 20).TrimEnd('\0').TrimEnd('\n').TrimEnd('\0');
|
Username = Encoding.ASCII.GetString(data, 0, 20).TrimEnd('\0').TrimEnd('\n').TrimEnd('\0');
|
||||||
// Remove unnecessary Symbols
|
// Remove unnecessary Symbols
|
||||||
this.Password = Encoding.ASCII.GetString(data, 20, 31).TrimEnd('\0').TrimEnd('\n').TrimEnd('\0');
|
Password = Encoding.ASCII.GetString(data, 20, 31).TrimEnd('\0').TrimEnd('\n').TrimEnd('\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
Span<byte> dataSpan = stackalloc byte[20 + 31];
|
Span<byte> dataSpan = stackalloc byte[20 + 31];
|
||||||
var usernameBytes = Encoding.ASCII.GetBytes(this.Username);
|
var usernameBytes = Encoding.ASCII.GetBytes(Username);
|
||||||
var passwordBytes = Encoding.ASCII.GetBytes(this.Password);
|
var passwordBytes = Encoding.ASCII.GetBytes(Password);
|
||||||
for (var i = 0; i < 20 || i < this.Username.Length; i++)
|
for (var i = 0; i < 20 || i < Username.Length; i++)
|
||||||
{
|
{
|
||||||
dataSpan[i] = usernameBytes[i];
|
dataSpan[i] = usernameBytes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < 31 || i < this.Password.Length; i++)
|
for (var i = 0; i < 31 || i < Password.Length; i++)
|
||||||
{
|
{
|
||||||
dataSpan[20 + i] = passwordBytes[i];
|
dataSpan[20 + i] = passwordBytes[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,5 @@ public enum OperationCode : ushort
|
||||||
CharacterDeletion = 16,
|
CharacterDeletion = 16,
|
||||||
CharacterDeletionResponse = 16,
|
CharacterDeletionResponse = 16,
|
||||||
CharacterSelection = 17,
|
CharacterSelection = 17,
|
||||||
CharacterSelectionSetGuildName = 19,
|
CharacterSelectionSetGuildName = 19
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,17 @@ public class ChannelSelectionResponsePacket : IPacket
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
Span<byte> data = stackalloc byte[1 + 16 + 2 + 1 + 132 * this.Characters.Length];
|
Span<byte> data = stackalloc byte[1 + 16 + 2 + 1 + 132 * Characters.Length];
|
||||||
data.Clear();
|
data.Clear();
|
||||||
data[0] = this.ChannelIsFullFlag;
|
data[0] = ChannelIsFullFlag;
|
||||||
Encoding.ASCII.GetBytes(this.Endpoint, data.Slice(1, 16));
|
Encoding.ASCII.GetBytes(Endpoint, data.Slice(1, 16));
|
||||||
BinaryPrimitives.WriteUInt16LittleEndian(data.Slice(17, 2), this.Port);
|
BinaryPrimitives.WriteUInt16LittleEndian(data.Slice(17, 2), Port);
|
||||||
data[19] = (byte)this.Characters.Length;
|
data[19] = (byte)Characters.Length;
|
||||||
|
|
||||||
// Character Data
|
// Character Data
|
||||||
for (var i = 0; i < Characters.Length; i++)
|
for (var i = 0; i < Characters.Length; i++)
|
||||||
{
|
{
|
||||||
int offset = 20 + (i * 132);
|
var offset = 20 + i * 132;
|
||||||
var character = Characters[i];
|
var character = Characters[i];
|
||||||
// Character Data
|
// Character Data
|
||||||
BinaryPrimitives.WriteInt32LittleEndian(data.Slice(offset, 4), i);
|
BinaryPrimitives.WriteInt32LittleEndian(data.Slice(offset, 4), i);
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class CharacterNameCheckPacketResponse : IPacket
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
Span<byte> data = stackalloc byte[1];
|
Span<byte> data = stackalloc byte[1];
|
||||||
data[0] = this.IsTaken ? (byte)1 : (byte)0;
|
data[0] = IsTaken ? (byte)1 : (byte)0;
|
||||||
return data.ToArray();
|
return data.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,15 @@ public class CharacterSelectionSetGuildNamePacket : IPacket
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
Span<byte> data = stackalloc byte[1 + (1 + 16 + 1) * this.GuildNames.Length];
|
Span<byte> data = stackalloc byte[1 + (1 + 16 + 1) * GuildNames.Length];
|
||||||
data.Clear();
|
data.Clear();
|
||||||
data[0] = (byte)this.GuildNames.Length;
|
data[0] = (byte)GuildNames.Length;
|
||||||
for (var i = 0; i < this.GuildNames.Length; i++)
|
for (var i = 0; i < GuildNames.Length; i++)
|
||||||
{
|
{
|
||||||
data[1 + (i * (1 + 16 + 1))] = (byte)i;
|
data[1 + i * (1 + 16 + 1)] = (byte)i;
|
||||||
Encoding.ASCII.GetBytes(this.GuildNames[i], data.Slice(2 + (i * (1 + 16 + 1)), 16));
|
Encoding.ASCII.GetBytes(GuildNames[i], data.Slice(2 + i * (1 + 16 + 1), 16));
|
||||||
// Null terminator
|
// Null terminator
|
||||||
data[18 + (i * (1 + 16 + 1))] = 0;
|
data[18 + i * (1 + 16 + 1)] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.ToArray();
|
return data.ToArray();
|
||||||
|
|
|
@ -14,38 +14,38 @@ public class LoginResponsePacket : IPacket
|
||||||
|
|
||||||
public void Deserialize(byte[] data)
|
public void Deserialize(byte[] data)
|
||||||
{
|
{
|
||||||
this.ResponseReason = (LoginResponseReason)data[0];
|
ResponseReason = (LoginResponseReason)data[0];
|
||||||
this.UnknownFlag = data[1];
|
UnknownFlag = data[1];
|
||||||
this.IsGameMaster = BitConverter.ToBoolean(data, 2);
|
IsGameMaster = BitConverter.ToBoolean(data, 2);
|
||||||
var channelAmount = BitConverter.ToUInt16(data, 3);
|
var channelAmount = BitConverter.ToUInt16(data, 3);
|
||||||
const int sizeOfServerChannelData = 5;
|
const int sizeOfServerChannelData = 5;
|
||||||
this.ChannelData = Enumerable.Repeat(0, channelAmount).Select(i => new ServerChannelData
|
ChannelData = Enumerable.Repeat(0, channelAmount).Select(i => new ServerChannelData
|
||||||
{
|
{
|
||||||
ServerId = BitConverter.ToUInt16(data, 5 + 0 + (i * sizeOfServerChannelData)),
|
ServerId = BitConverter.ToUInt16(data, 5 + 0 + i * sizeOfServerChannelData),
|
||||||
ChannelId = BitConverter.ToUInt16(data, 5 + 2 + (i * sizeOfServerChannelData)),
|
ChannelId = BitConverter.ToUInt16(data, 5 + 2 + i * sizeOfServerChannelData),
|
||||||
LoadPercentage = data[5 + 4 + (i * sizeOfServerChannelData)]
|
LoadPercentage = data[5 + 4 + i * sizeOfServerChannelData]
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
{
|
{
|
||||||
const int sizeOfServerChannelData = 5;
|
const int sizeOfServerChannelData = 5;
|
||||||
Span<byte> dataSpan = stackalloc byte[5 + (this.ChannelData.Length * sizeOfServerChannelData)];
|
Span<byte> dataSpan = stackalloc byte[5 + ChannelData.Length * sizeOfServerChannelData];
|
||||||
dataSpan.Clear();
|
dataSpan.Clear();
|
||||||
dataSpan[0] = (byte)this.ResponseReason;
|
dataSpan[0] = (byte)ResponseReason;
|
||||||
dataSpan[1] = this.UnknownFlag;
|
dataSpan[1] = UnknownFlag;
|
||||||
dataSpan[2] = BitConverter.GetBytes(this.IsGameMaster)[0];
|
dataSpan[2] = BitConverter.GetBytes(IsGameMaster)[0];
|
||||||
BinaryPrimitives.WriteUInt16LittleEndian(dataSpan.Slice(3, 2), (ushort)this.ChannelData.Length);
|
BinaryPrimitives.WriteUInt16LittleEndian(dataSpan.Slice(3, 2), (ushort)ChannelData.Length);
|
||||||
|
|
||||||
for (var i = 0; i < this.ChannelData.Length; i++)
|
for (var i = 0; i < ChannelData.Length; i++)
|
||||||
{
|
{
|
||||||
var bytesOfServerId = BitConverter.GetBytes(this.ChannelData[i].ServerId);
|
var bytesOfServerId = BitConverter.GetBytes(ChannelData[i].ServerId);
|
||||||
var bytesOfChannelId = BitConverter.GetBytes(this.ChannelData[i].ChannelId);
|
var bytesOfChannelId = BitConverter.GetBytes(ChannelData[i].ChannelId);
|
||||||
dataSpan[5 + 0 + (i * sizeOfServerChannelData)] = bytesOfServerId[0];
|
dataSpan[5 + 0 + i * sizeOfServerChannelData] = bytesOfServerId[0];
|
||||||
dataSpan[5 + 1 + (i * sizeOfServerChannelData)] = bytesOfServerId[1];
|
dataSpan[5 + 1 + i * sizeOfServerChannelData] = bytesOfServerId[1];
|
||||||
dataSpan[5 + 2 + (i * sizeOfServerChannelData)] = bytesOfChannelId[0];
|
dataSpan[5 + 2 + i * sizeOfServerChannelData] = bytesOfChannelId[0];
|
||||||
dataSpan[5 + 3 + (i * sizeOfServerChannelData)] = bytesOfChannelId[1];
|
dataSpan[5 + 3 + i * sizeOfServerChannelData] = bytesOfChannelId[1];
|
||||||
dataSpan[5 + 4 + (i * sizeOfServerChannelData)] = this.ChannelData[i].LoadPercentage;
|
dataSpan[5 + 4 + i * sizeOfServerChannelData] = ChannelData[i].LoadPercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSpan.ToArray();
|
return dataSpan.ToArray();
|
||||||
|
|
|
@ -3,6 +3,10 @@ namespace Wonderking.Packets;
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||||
public class PacketIdAttribute : Attribute
|
public class PacketIdAttribute : Attribute
|
||||||
{
|
{
|
||||||
public PacketIdAttribute(OperationCode code) => this.Code = code;
|
public PacketIdAttribute(OperationCode code)
|
||||||
|
{
|
||||||
|
Code = code;
|
||||||
|
}
|
||||||
|
|
||||||
public OperationCode Code { get; }
|
public OperationCode Code { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class ByteArrayConverter : JsonConverter<byte[]>
|
||||||
{
|
{
|
||||||
return hexData.Split('-').Select(b => Convert.ToByte(b, 16)).ToArray();
|
return hexData.Split('-').Select(b => Convert.ToByte(b, 16)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new JsonException("Hex string is null.");
|
throw new JsonException("Hex string is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/>
|
||||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.110">
|
<PackageReference Include="Meziantou.Analyzer" Version="2.0.110">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0"/>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
|
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.8.14">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
@ -39,6 +39,6 @@
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Game\Writer\" />
|
<Folder Include="Game\Writer\"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in a new issue