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

This commit is contained in:
Timothy Schenk 2023-11-19 17:07:28 +01:00
parent db63e581e5
commit 9f3007b10e
40 changed files with 416 additions and 379 deletions

View file

@ -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:

View file

@ -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];
} }
} }

View file

@ -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()

View file

@ -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);
} }

View file

@ -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));
} }
} }

View file

@ -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;
} }
} }

View file

@ -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]

View file

@ -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; }

View file

@ -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)

View file

@ -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

View file

@ -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);
} }

View file

@ -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
{ {

View file

@ -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);
}
} }

View file

@ -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; }

View file

@ -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,

View file

@ -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);
} }
} }

View file

@ -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);
}
} }

View file

@ -8,4 +8,3 @@ public struct CraftMaterial
public uint ID; public uint ID;
public uint Amount; public uint Amount;
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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;

View file

@ -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; }
} }

View file

@ -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; }
} }

View file

@ -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;

View file

@ -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

View file

@ -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
}; };
} }

View file

@ -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();
}
} }

View file

@ -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];
} }

View file

@ -13,5 +13,5 @@ public enum OperationCode : ushort
CharacterDeletion = 16, CharacterDeletion = 16,
CharacterDeletionResponse = 16, CharacterDeletionResponse = 16,
CharacterSelection = 17, CharacterSelection = 17,
CharacterSelectionSetGuildName = 19, CharacterSelectionSetGuildName = 19
} }

View file

@ -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);

View file

@ -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();
} }
} }

View file

@ -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();

View file

@ -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();

View file

@ -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; }
} }

View file

@ -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.");
} }