Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Sphere/Sphere.Client/Services/Handlers/BaseHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using Sphere.Common.Helpers.Extensions;
using Sphere.Common.Interfaces.Tcp;
using Sphere.Common.Packets;

Expand All @@ -19,7 +18,6 @@ protected BaseHandler(ILogger logger, IClientAccessor tcpClientAccessor)
protected async Task SendPacket(byte[] rcvBuffer)
{
await _clientAccessor.Client.WriteAsync(rcvBuffer);
_logger.PacketSent(rcvBuffer, _clientAccessor.ClientId);
}

protected async Task TerminateConnection()
Expand Down
11 changes: 9 additions & 2 deletions Sphere/Sphere.Client/Services/Readers/SpherePacketReader.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using Sphere.Common.Interfaces.Packets;
using Microsoft.Extensions.Logging;
using Sphere.Common.Helpers.Extensions;
using Sphere.Common.Interfaces.Packets;
using Sphere.Common.Interfaces.Readers;
using Sphere.Common.Interfaces.Tcp;
using Sphere.Services.Services.Tcp;

namespace Sphere.Services.Readers
{
Expand All @@ -13,11 +16,13 @@ namespace Sphere.Services.Readers
public class SpherePacketReader : IPacketReader
{
private readonly IClientAccessor _tcpClientAccessor;
private readonly ILogger<SphereTcpClient> _logger;
private PacketBase _current;

public SpherePacketReader(IClientAccessor tcpClientAccessor)
public SpherePacketReader(IClientAccessor tcpClientAccessor, ILogger<SphereTcpClient> logger)
{
_tcpClientAccessor = tcpClientAccessor;
_logger = logger;
}

public PacketBase Current => _current;
Expand Down Expand Up @@ -55,6 +60,8 @@ public async ValueTask<bool> MoveNextAsync()

_current = basePacket;

_logger.PacketReceived(_current.OriginalMessage, _tcpClientAccessor.ClientId);

return true;
}

Expand Down
16 changes: 13 additions & 3 deletions Sphere/Sphere.Client/Services/Tcp/SphereTcpClient.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
using Sphere.Common.Interfaces.Tcp;
using Microsoft.Extensions.Logging;
using Sphere.Common.Helpers.Extensions;
using Sphere.Common.Interfaces.Tcp;
using System.Net.Sockets;

namespace Sphere.Services.Services.Tcp
{
public class SphereTcpClient : ITcpClient, IDisposable
{
private readonly TcpClient _tcpClient;
private readonly IClientAccessor _clientAccessor;
private readonly ILogger<SphereTcpClient> _logger;

public SphereTcpClient(TcpClient tcpClient)
public SphereTcpClient(ILogger<SphereTcpClient> logger, TcpClient tcpClient, IClientAccessor clientAccessor)
{
_tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
_clientAccessor = clientAccessor;
_logger = logger;
}

public bool Connected => _tcpClient.Connected;
Expand All @@ -20,7 +26,11 @@ public SphereTcpClient(TcpClient tcpClient)

public async Task<int> ReadAsync(byte[] buffer, int offset, int count) => await GetStream().ReadAsync(buffer, offset, count);

public async ValueTask WriteAsync(byte[] buffer) => await GetStream().WriteAsync(buffer);
public async ValueTask WriteAsync(byte[] buffer)
{
await GetStream().WriteAsync(buffer);
_logger.PacketSent(buffer, _clientAccessor.ClientId);
}

public Stream GetStream() => _tcpClient.GetStream();

Expand Down
67 changes: 67 additions & 0 deletions Sphere/Sphere.Client/Services/Utils/PacketDefinitionParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Sphere.Common.Interfaces.Utils;
using Sphere.Common.Packets;
using Sphere.Common.Types;

namespace Sphere.Services.Services.Utils
{
/// <summary>
/// Reads packet definitions and adds into a static library.
/// </summary>
public class PacketDefinitionParser : IPacketDefinitionParser
{
// Move to settings or wherever
private const string Folder = "../PacketDefinitions";
private const char Separator = '\t';

private static readonly HashSet<string> IgnoreParts = new HashSet<string> { "__undef", "skip", "skip_1", "skip_100", "delimiter_test", "next_field", "field_length", "level_maybe" };

/// <summary>
/// Loads .spdp files from configured folder, parses it and create a ditionary of packet definitions.
/// </summary>
/// <returns></returns>
public Dictionary<string, PacketDefinition?> Load()
{
if (!Directory.Exists(Folder))
{
return new Dictionary<string, PacketDefinition?>();
}

var parts = Directory.EnumerateFiles(Folder, "*.spdp", SearchOption.AllDirectories).Select(file =>
{
try
{
var parts = ReadFile(file);
var definition = new PacketDefinition(Path.GetFileNameWithoutExtension(file), parts.ToDictionary());

return definition;
}
catch (Exception)
{
return null;
}
});

return parts.ToDictionary(x => x.Name);
}

private IEnumerable<KeyValuePair<string, vByte>> ReadFile(string file)
{
var content = File.ReadAllLines(file);
return content.Select(str =>
{
var split = str.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
var name = split[0];
var value = split[9];

if (IgnoreParts.Contains(name))
{
name = Guid.NewGuid().ToString("N");
}

var bytes = Enumerable.Chunk(value, 8);

return new KeyValuePair<string, vByte>(name, new vByte(bytes.Select(b => Convert.ToByte(new string(b), 2)).ToArray(), (ushort)value.Length));
});
}
}
}
13 changes: 13 additions & 0 deletions Sphere/Sphere.Common/Enums/EntityActionTypeEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Sphere.Common.Enums
{
internal enum EntityActionTypeEnum
{
SET_POSITION = 0x06,
FULL_SPAWN = 0x7C,
FULL_SPAWN_2 = 0x7D,
ATTACK = 0x2A,
INTERACT = 0xA,
UNKNOWN = 0x14,
UNDEF
}
}
119 changes: 119 additions & 0 deletions Sphere/Sphere.Common/Enums/GameObjectTypeEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
namespace Sphere.Common.Enums
{
public enum GameObjectTypeEnum : ushort
{
Despawn = 0,
UpdateState = 2,
Player = 4,
Token = 8,
Mutator = 30,
SeedCastle = 40,
XpPillDegree = 47,
DoorEntrance = 60,
DoorExit = 61,
TeleportWithTarget = 62,
Teleport = 63,
DungeonEntrance = 65,
TeleportWild = 67,
TokenMultiuse = 66,
TradeLicense = 68,
MobSpawner = 70,
TournamentTeleport = 71,
TutorialMessage = 72,
ScrollLegend = 90,
ScrollRecipe = 91,
Mission = 95,
TokenIsland = 104,
TokenIslandGuest = 105,
NpcQuestTitle = 205,
NpcQuestKarma = 208,
NpcQuestDegree = 209,
Monster = 210,
MonsterFlyer = 211,
NpcTrade = 213,
NpcBanker = 225,
Bead = 236,
NpcGuilder = 239,
BackpackLarge = 400,
BackpackSmall = 401,
Sack = 405,
Chest = 406,
SackMobLoot = 407,
MantraBookSmall = 409,
RecipeBook = 410,
MantraBookLarge = 411,
MantraBookGreat = 412,
MapBook = 413,
ChestInDungeon = 417,
KeyBarn = 418,
PowderFinale = 451,
PowderSingleTarget = 453,
PowderAmilus = 454,
PowderAoE = 455,
ElixirCastle = 471,
ElixirTrap = 472,
WeaponSword = 500,
WeaponAxe = 501,
WeaponCrossbow = 502,
Arrows = 503,
RingDiamond = 551,
RingRuby = 552,
Ruby = 553,
RingGold = 555,
AlchemyMineral = 600,
AlchemyPlant = 601,
AlchemyMetal = 602,
FoodApple = 650,
FoodPear = 651,
FoodMeat = 652,
FoodBread = 653,
FoodFish = 655,
AlchemyBrushwood = 700,
Key = 701,
Map = 703,
Inkpot = 704,
Firecracker = 705,
Ear = 706,
EarString = 708,
MonsterPart = 709,
Firework = 712,
InkpotBroken = 715,
ArmorChest = 750,
ArmorAmulet = 751,
ArmorBoots = 752,
ArmorGloves = 754,
ArmorBelt = 755,
ArmorShield = 756,
ArmorHelmet = 757,
ArmorPants = 758,
ArmorBracelet = 759,
Ring = 760,
ArmorRobe = 761,
RingGolem = 762,
AlchemyPot = 800,
AlchemyFurnace = 803,
Blueprint = 804,
Workshop = 805,
QuestArmorChest = 949,
QuestArmorChest2 = 950, // unused?
QuestArmorBoots = 952,
QuestArmorGloves = 953,
QuestArmorBelt = 954,
QuestArmorShield = 955,
QuestArmorHelmet = 956,
QuestArmorPants = 957,
QuestArmorBracelet = 958, // unused?
QuestArmorRing = 959, // unused?
QuestArmorRobe = 960,
QuestWeaponSword = 961,
QuestWeaponAxe = 962,
QuestWeaponCrossbow = 963,
SpecialGuild = 976, // sometimes different
SpecialAbility = 977, // same type for specialization itself
SpecialAbilitySteal = 979, // same type for specialization itself
ArmorHelmetPremium = 990,
MantraWhite = 1000,
MantraBlack = 1001,
Unknown = ushort.MaxValue
}
}
Loading