[v0.0.2] you can enter menu now. but still early state

todo: improve code and finish base structures
This commit is contained in:
BreadDEV 2024-03-05 17:37:18 +07:00
parent ad23f95319
commit 8c6a533918
51 changed files with 1425 additions and 433 deletions

View file

@ -0,0 +1,26 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Logic.Avatar;
public class LogicAvatarGame : LogicBase
{
public LogicAvatarGame() : base(20486)
{
}
public override void Destruct()
{
base.Destruct();
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
}
}

View file

@ -0,0 +1,75 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Logic.Player;
using Supercell.GUT.Titan.Logic.DataStream;
using Supercell.GUT.Titan.Logic.Math;
using Supercell.GUT.Titan.Logic.Util;
namespace Supercell.GUT.Logic.Avatar;
public class LogicClientAvatar : LogicBase
{
public LogicLong Id { get; set; }
public int ActiveMission { get; set; }
public string Name { get; set; }
public string AvatarCode { get; set; }
public LogicArrayList<LogicAvatarGame> AvatarGames { get; set; }
public LogicArrayList<int> MissionStatus { get; set; }
public LogicPlayerAttributes PlayerAttributes { get; set; }
public LogicInventory Inventory { get; set; }
public LogicPlayerStats PlayerStats { get; set; }
public int TutorialFlags { get; set; }
public LogicClientAvatar() : base(20486)
{
this.Id = new LogicLong();
this.ActiveMission = -1;
this.Name = string.Empty;
this.AvatarCode = string.Empty;
this.AvatarGames = new LogicArrayList<LogicAvatarGame>();
this.MissionStatus = new LogicArrayList<int>();
this.PlayerAttributes = new LogicPlayerAttributes(20486);
this.Inventory = new LogicInventory(20486);
this.PlayerStats = new LogicPlayerStats(20486);
}
public override void Destruct()
{
base.Destruct();
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
checksumEncoder.WriteLong(this.Id);
checksumEncoder.WriteInt(this.ActiveMission);
checksumEncoder.WriteString(this.Name);
checksumEncoder.WriteString(this.AvatarCode);
checksumEncoder.WriteInt(this.AvatarGames.Size());
for (int i = 0; i < this.AvatarGames.Size(); i++)
{
this.AvatarGames[i].Encode(checksumEncoder);
}
checksumEncoder.WriteInt(this.MissionStatus.Size());
for (int i = 0; i < this.MissionStatus.Size(); i++)
{
checksumEncoder.WriteInt(this.MissionStatus[i]);
}
this.PlayerAttributes.Encode(checksumEncoder);
this.Inventory.Encode(checksumEncoder);
this.PlayerStats.Encode(checksumEncoder);
checksumEncoder.WriteInt(this.TutorialFlags);
}
}

View file

@ -1,5 +1,4 @@
using Supercell.GUT.Titan.Encoding;
using Supercell.GUT.Titan.Encoding.Streamed;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Logic.Base;
@ -31,7 +30,7 @@ public abstract class LogicBase
{
this.Destruct();
ByteStream byteStream = new ByteStream(0);
ByteStream byteStream = new ByteStream();
logicBase.Encode(byteStream);
byteStream.ResetOffset();

View file

@ -0,0 +1,59 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Logic.Game;
public class LogicGameCalendar : LogicBase
{
public LogicGameCalendar() : base(0)
{
;
}
public LogicGameCalendar(int logicDataVersion) : base(logicDataVersion)
{
;
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
checksumEncoder.WriteInt(0);
checksumEncoder.WriteByte(0);
checksumEncoder.WriteByte(0);
checksumEncoder.WriteByte(0);
checksumEncoder.WriteByte(0);
checksumEncoder.WriteByte(0);
checksumEncoder.WriteInt(0);
checksumEncoder.WriteInt(0);
}
public override void Decode(ByteStream byteStream)
{
;
}
public void CalculateDateVariablesFromDayIndex(int index)
{
;
}
public void AddSeconds(int seconds)
{
;
}
public int GetRemainingSeconds(LogicGameCalendar gameCalendar)
{
return 0;
}
public void CalculateMonth(int month, bool isLeapYear)
{
;
}
public override void Destruct()
{
;
}
}

View file

@ -1,5 +1,5 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;

View file

@ -1,5 +1,5 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;

View file

@ -1,5 +1,5 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;

View file

@ -0,0 +1,39 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;
[VersionedMessage(20103)]
public class LoginFailedMessage : VersionedMessage
{
public int ErrorCode { get; set; }
public LoginFailedMessage() : base(0)
{
this.ErrorCode = 0;
}
public override void Encode()
{
base.Encode();
this.ByteStream.WriteInt(this.ErrorCode);
}
public override void Decode()
{
base.Decode();
this.ErrorCode = this.ByteStream.ReadInt();
}
public override int GetMessageType()
{
return 20103;
}
public override int GetServiceNodeType()
{
return 1;
}
}

View file

@ -0,0 +1,79 @@
using Supercell.GUT.Logic.Game;
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;
[VersionedMessage(20104)]
public class LoginOkMessage : VersionedMessage
{
public int PrimaryAvatarIdHigherInt { get; set; }
public int PrimaryAvatarIdLowerInt { get; set; }
public string? Fingerprint { get; set; }
public int Env { get; set; }
public int ServerVersion { get; set; }
public int SessionCount { get; set; }
public LogicGameCalendar ServerCalendar { get; set; }
public LoginOkMessage() : base(0)
{
this.PrimaryAvatarIdHigherInt = 0;
this.PrimaryAvatarIdLowerInt = 0;
this.Fingerprint = string.Empty;
this.Env = 0;
this.ServerVersion = 0;
this.SessionCount = 0;
this.ServerCalendar = new LogicGameCalendar();
}
public override void Encode()
{
base.Encode();
this.ByteStream.WriteInt(0);
this.ByteStream.WriteInt(0);
this.ByteStream.WriteInt(this.PrimaryAvatarIdHigherInt);
this.ByteStream.WriteInt(this.PrimaryAvatarIdLowerInt);
this.ByteStream.WriteInt(0);
this.ByteStream.WriteInt(this.Env);
this.ByteStream.WriteInt(this.ServerVersion);
this.ByteStream.WriteInt(this.SessionCount);
this.ByteStream.WriteString(null);
this.ServerCalendar.Encode(this.ByteStream);
this.ByteStream.WriteString(null);
this.ByteStream.WriteString(this.Fingerprint);
this.ByteStream.WriteInt(0);
}
public override void Decode()
{
base.Decode();
// TODO
}
public override int GetMessageType()
{
return 20104;
}
public override int GetServiceNodeType()
{
return 1;
}
public override void Destruct()
{
base.Destruct();
this.PrimaryAvatarIdHigherInt = 0;
this.PrimaryAvatarIdLowerInt = 0;
this.Fingerprint = string.Empty;
this.Env = 0;
this.ServerVersion = 0;
this.SessionCount = 0;
}
}

View file

@ -0,0 +1,73 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;
[VersionedMessage(10102)]
public class LoginUsingSessionMessage : VersionedMessage
{
public int AccountIdHigherInt { get; set; }
public int AccountIdLowerInt { get; set; }
public int ClientGameVersion { get; set; }
public string? SessionKey { get; set; }
public string? GamecenterId { get; set; }
public LoginUsingSessionMessage() : base(0)
{
this.AccountIdHigherInt = 0;
this.AccountIdLowerInt = 0;
this.ClientGameVersion = 0;
this.SessionKey = string.Empty;
this.SessionKey = string.Empty;
}
public override void Encode()
{
base.Encode();
this.ByteStream.WriteInt(this.AccountIdHigherInt);
this.ByteStream.WriteInt(this.AccountIdLowerInt);
this.ByteStream.WriteInt(this.ClientGameVersion);
this.ByteStream.WriteInt(0);
this.ByteStream.WriteString(this.SessionKey);
this.ByteStream.WriteString(null);
this.ByteStream.WriteString(null);
this.ByteStream.WriteString(this.GamecenterId);
}
public override void Decode()
{
base.Decode();
this.AccountIdHigherInt = this.ByteStream.ReadInt();
this.AccountIdLowerInt = this.ByteStream.ReadInt();
this.ClientGameVersion = this.ByteStream.ReadInt();
this.ByteStream.ReadInt();
this.SessionKey = this.ByteStream.ReadString();
this.ByteStream.ReadString();
this.ByteStream.ReadString();
this.GamecenterId = this.ByteStream.ReadString();
}
public override int GetMessageType()
{
return 10102;
}
public override int GetServiceNodeType()
{
return 1;
}
public override void Destruct()
{
base.Destruct();
this.AccountIdHigherInt = 0;
this.AccountIdLowerInt = 0;
this.ClientGameVersion = 0;
this.SessionKey = string.Empty;
this.SessionKey = string.Empty;
}
}

View file

@ -1,6 +1,6 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Util;
using Supercell.GUT.Titan.Logic.Message;
using Supercell.GUT.Titan.Logic.Util;
namespace Supercell.GUT.Logic.Message.Account;

View file

@ -1,5 +1,5 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Account;

View file

@ -0,0 +1,46 @@
using Supercell.GUT.Logic.Avatar;
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Avatar;
[VersionedMessage(20201)]
public class AvatarDataMessage : VersionedMessage
{
public LogicClientAvatar LogicClientAvatar { get; set; }
public AvatarDataMessage() : base(0)
{
;
}
public override void Destruct()
{
base.Destruct();
}
public override void Encode()
{
base.Encode();
LogicClientAvatar.Encode(ByteStream);
}
public override void Decode()
{
base.Decode();
LogicClientAvatar = new LogicClientAvatar();
LogicClientAvatar.Decode(ByteStream);
}
public override int GetMessageType()
{
return 20201;
}
public override int GetServiceNodeType()
{
return 3;
}
}

View file

@ -0,0 +1,51 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Logic.Message.Avatar;
[VersionedMessage(10201)]
public class SelectAvatarMessage : VersionedMessage
{
public int AvatarIdHigherInt { get; set; }
public int AvatarIdLowerInt { get; set; }
public SelectAvatarMessage() : base(0)
{
AvatarIdHigherInt = 0;
AvatarIdLowerInt = 0;
}
public override void Encode()
{
base.Encode();
ByteStream.WriteInt(AvatarIdHigherInt);
ByteStream.WriteInt(AvatarIdLowerInt);
}
public override void Decode()
{
base.Decode();
AvatarIdHigherInt = ByteStream.ReadInt();
AvatarIdLowerInt = ByteStream.ReadInt();
}
public override int GetMessageType()
{
return 10201;
}
public override int GetServiceNodeType()
{
return 3;
}
public override void Destruct()
{
base.Destruct();
AvatarIdHigherInt = 0;
AvatarIdLowerInt = 0;
}
}

View file

@ -1,5 +1,5 @@
using Supercell.GUT.Logic.Message.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
using System.Collections.Immutable;
using System.Reflection;

View file

@ -0,0 +1,34 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Logic.Player;
public class LogicInventory : LogicBase
{
public LogicInventory(int logicDataVersion) : base(logicDataVersion)
{
}
public override void Destruct()
{
base.Destruct();
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
checksumEncoder.WriteInt(0);
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
int count = byteStream.ReadInt();
for (int i = 0; i < count; i++)
{
}
}
}

View file

@ -0,0 +1,94 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Logic.Team;
using Supercell.GUT.Titan.Logic.DataStream;
using Supercell.GUT.Titan.Logic.Util;
namespace Supercell.GUT.Logic.Player;
public class LogicPlayerAttributes : LogicBase
{
public int ExpLevel { get; set; }
public int ExpPoints { get; set; }
public int Money { get; set; }
public int Diamonds { get; set; }
public int LeagueMmr { get; set; }
public int LeagueMmrKFactor { get; set; }
public string TeamName { get; set; }
public LogicArrayList<LogicTeamUnit> TeamUnits { get; set; }
public LogicArrayList<string> ReadHandbooks { get; set; }
public LogicPlayerAttributes(int logicDataVersion) : base(logicDataVersion)
{
this.TeamName = string.Empty;
this.TeamUnits = new LogicArrayList<LogicTeamUnit>();
for (int i = 0; i <= 4; i++)
{
LogicTeamUnit logicTeamUnit = LogicTeamUnit.CreateDefaultUnit(i);
switch (i)
{
case 0:
logicTeamUnit.SetSkill("sk_magnum0");
break;
case 1:
logicTeamUnit.SetSkill("sk_grenade0");
break;
case 2:
logicTeamUnit.SetSkill("sk_magnum0");
break;
case 3:
logicTeamUnit.SetSkill("sk_magnum0");
break;
case 4:
logicTeamUnit.SetSkill("sk_grenade0");
break;
default:
break;
}
this.TeamUnits.Add(logicTeamUnit);
}
this.ReadHandbooks = new LogicArrayList<string>();
}
public override void Destruct()
{
base.Destruct();
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
checksumEncoder.WriteInt(this.ExpLevel);
checksumEncoder.WriteInt(this.ExpPoints);
checksumEncoder.WriteInt(this.Money);
checksumEncoder.WriteInt(this.Diamonds);
checksumEncoder.WriteInt(this.LeagueMmr);
checksumEncoder.WriteInt(this.LeagueMmrKFactor);
checksumEncoder.WriteString(this.TeamName);
checksumEncoder.WriteInt(this.TeamUnits.Size());
for (int i = 0; i < this.TeamUnits.Size(); i++)
{
this.TeamUnits[i].Encode(checksumEncoder);
}
checksumEncoder.WriteInt(this.ReadHandbooks.Size());
for (int i = 0; i < this.ReadHandbooks.Size(); i++)
{
checksumEncoder.WriteString(this.ReadHandbooks[i]);
}
checksumEncoder.WriteInt(-1);
checksumEncoder.WriteInt(0);
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
}
}

View file

@ -0,0 +1,58 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Logic.Player;
public class LogicPlayerStats : LogicBase
{
public int Score { get; set; }
public int MatchCount { get; set; }
public int WinCount { get; set; }
public int KillCount { get; set; }
public LogicPlayerStats() : base(20486)
{
this.Score = 0;
this.MatchCount = 0;
this.WinCount = 0;
this.KillCount = 0;
}
public LogicPlayerStats(int logicDataVersion) : base(logicDataVersion)
{
this.Score = 0;
this.MatchCount = 0;
this.WinCount = 0;
this.KillCount = 0;
}
public override void Destruct()
{
base.Destruct();
this.Score = 0;
this.MatchCount = 0;
this.WinCount = 0;
this.KillCount = 0;
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
checksumEncoder.WriteInt(this.Score);
checksumEncoder.WriteInt(this.MatchCount);
checksumEncoder.WriteInt(this.WinCount);
checksumEncoder.WriteInt(this.KillCount);
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
this.Score = byteStream.ReadInt();
this.MatchCount = byteStream.ReadInt();
this.WinCount = byteStream.ReadInt();
this.KillCount = byteStream.ReadInt();
}
}

View file

@ -0,0 +1,54 @@
using Supercell.GUT.Logic.Base;
using Supercell.GUT.Titan.Logic.DataStream;
using Supercell.GUT.Titan.Logic.Util;
namespace Supercell.GUT.Logic.Team;
public class LogicTeamUnit : LogicBase
{
public string Name { get; set; }
public LogicArrayList<string> Skills { get; set; }
public LogicTeamUnit() : base(0)
{
this.Skills = new LogicArrayList<string>();
}
public override void Destruct()
{
base.Destruct();
}
public override void Encode(ChecksumEncoder checksumEncoder)
{
base.Encode(checksumEncoder);
checksumEncoder.WriteInt(0);
checksumEncoder.WriteString(this.Name);
checksumEncoder.WriteInt(this.Skills.Size());
for (int i = 0; i < this.Skills.Size(); i++)
{
checksumEncoder.WriteString(this.Skills[i]);
}
checksumEncoder.WriteString(null);
}
public override void Decode(ByteStream byteStream)
{
base.Decode(byteStream);
}
public void SetSkill(string skill)
{
this.Skills.Add(skill);
}
public static LogicTeamUnit CreateDefaultUnit(int index)
{
return new LogicTeamUnit
{
Name = $"un_default{index}"
};
}
}

View file

@ -0,0 +1,23 @@
namespace Supercell.GUT.SDK;
internal static class Program
{
private static async Task Main(string[] args)
{
Console.Title = "Supercell.GUT | SDK";
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://*:80");
WebApplication app = builder.Build();
app.MapGet("/fece25cfc941db1a5bb3e79d4e6a60c34659f49e/fingerprint.json", GetFingerprintJSON); // hardcode! maybe later i will fix it
await app.RunAsync();
}
private static string GetFingerprintJSON(HttpContext context)
{
return "{\"files\":[{\"sha\":\"505f650e5cabad8f139687c3f9aa66712d883a40\",\"file\":\"data\\/about.csv\",\"checksum\":\"71befcab\"},{\"sha\":\"51fde1a650aa0b66333ad5b66f59b22e8e54c4e5\",\"file\":\"data\\/ai_units.csv\",\"checksum\":\"afc97037\"},{\"sha\":\"19d3b1573cbd3ed59ee337c89bc5f82e8f30c68a\",\"file\":\"data\\/avatar.csv\",\"checksum\":\"f2eb9b6b\"},{\"sha\":\"0482673d8a493c8903babaf4066985e26018b919\",\"file\":\"data\\/billing_packages.csv\",\"checksum\":\"ce55b6c9\"},{\"sha\":\"97b4e6e365c9c110f38e5d55871512b75ce4bc3a\",\"file\":\"data\\/credits.csv\",\"checksum\":\"32376eed\"},{\"sha\":\"3cc18120f0fd00e073ace85d9326f38ce93b1cd7\",\"file\":\"data\\/cutscene.csv\",\"checksum\":\"b36efeb1\"},{\"sha\":\"b4dea5cb966a9a55eb050bdcab3cc39c6108509e\",\"file\":\"data\\/gadget.csv\",\"checksum\":\"4576288d\"},{\"sha\":\"03a0a7661ef1024d668ab0c5485696b05ccc5092\",\"file\":\"data\\/game_const.csv\",\"checksum\":\"e11bbf82\"},{\"sha\":\"fafee2358474f289ddefb241d6c8337908dc8168\",\"file\":\"data\\/gamelevel.csv\",\"checksum\":\"995dbb23\"},{\"sha\":\"a633224eee7bccb4ad0b10945694d7a70c5ad93d\",\"file\":\"data\\/gui.csv\",\"checksum\":\"27230b9d\"},{\"sha\":\"dee03d769deb41f0d823a77b8f95deccd5892fba\",\"file\":\"data\\/handbook.csv\",\"checksum\":\"e489859a\"},{\"sha\":\"ebe15e0d095677a16a3a2f466ce5cc8dd1972931\",\"file\":\"data\\/inboxmessage.csv\",\"checksum\":\"2fef1fae\"},{\"sha\":\"c0d921b74e476ea85470dfe97ca5de0b498764f6\",\"file\":\"data\\/item.csv\",\"checksum\":\"9ae439cd\"},{\"sha\":\"1e8b8532d5b6f2f9c129e6870f3b4529bb926479\",\"file\":\"data\\/lang.csv\",\"checksum\":\"b0acc094\"},{\"sha\":\"91e08d3857aab5ecceda43f9ae6b1d25def92f7c\",\"file\":\"data\\/leagues.csv\",\"checksum\":\"a448bd6e\"},{\"sha\":\"84b7125afd12c834e98ba0fd7eda3ba3c76246d7\",\"file\":\"data\\/level.csv\",\"checksum\":\"359e1925\"},{\"sha\":\"fe2aec13f1855e01ef6f8b255f0e7bf48cb58179\",\"file\":\"data\\/mission.csv\",\"checksum\":\"368649a8\"},{\"sha\":\"551df4fb20dba5a20e9281e50682d03f99859c9e\",\"file\":\"data\\/mission_tree.csv\",\"checksum\":\"55276023\"},{\"sha\":\"ae3ff2b07fcf5cef9a0f642c2ce6eae6ac00f0cd\",\"file\":\"data\\/moneybag.csv\",\"checksum\":\"29c04cff\"},{\"sha\":\"a8e4643f7157624432b6066e4d09d3722c40c4f3\",\"file\":\"data\\/readingtimes.csv\",\"checksum\":\"1e7bdc9b\"},{\"sha\":\"953289348875f3d8f6502d6cc1f60ea333841f8a\",\"file\":\"data\\/shop.csv\",\"checksum\":\"20449e2e\"},{\"sha\":\"a0f879b889aa8a25dcf03bf2d2bde85d9544600e\",\"file\":\"data\\/skill.csv\",\"checksum\":\"61288ccd\"},{\"sha\":\"e4c8e78e8aa71b70feb8c0959fd4c9a7e183bfbd\",\"file\":\"data\\/sounds.csv\",\"checksum\":\"195e7e52\"},{\"sha\":\"20495a2034755d8042016965ccea119f2efb173d\",\"file\":\"data\\/sounds_ipad1.csv\",\"checksum\":\"1531642f\"},{\"sha\":\"3b5047a6c8fab85bb8b0b313b8faabd61151bea1\",\"file\":\"data\\/speedup.csv\",\"checksum\":\"c96ef3ea\"},{\"sha\":\"1388ecfea65b98d1e9e4be785dac1a8a5964df57\",\"file\":\"data\\/trainingtimes.csv\",\"checksum\":\"811f4bd1\"},{\"sha\":\"a3055faddd0a1eff4f4da59df958235e3e5521c9\",\"file\":\"data\\/unit.csv\",\"checksum\":\"3c1ba78c\"},{\"sha\":\"6d37f4b27604df00c356e6776c6639b2e06a3669\",\"file\":\"data\\/upgrade.csv\",\"checksum\":\"e5f57998\"},{\"sha\":\"de893824bdf5e43ac377b276520ec65f399bb987\",\"file\":\"data\\/weapon.csv\",\"checksum\":\"a3079a59\"},{\"sha\":\"828dc22a8256dc0ffbc790983ad6a535221fe01d\",\"file\":\"gut.ini\",\"checksum\":\"601b736\"},{\"sha\":\"828dc22a8256dc0ffbc790983ad6a535221fe01d\",\"file\":\"gut_ipad2.ini\",\"checksum\":\"601b736\"},{\"sha\":\"828dc22a8256dc0ffbc790983ad6a535221fe01d\",\"file\":\"gut_ipad3.ini\",\"checksum\":\"601b736\"},{\"sha\":\"0d643a9c5bf2b8be58ba76cc0b3d25d84618a305\",\"file\":\"gut_iphone3.ini\",\"checksum\":\"5e8a6d2c\"},{\"sha\":\"0d643a9c5bf2b8be58ba76cc0b3d25d84618a305\",\"file\":\"gut_iphone4.ini\",\"checksum\":\"5e8a6d2c\"}],\"sha\":\"fece25cfc941db1a5bb3e79d4e6a60c34659f49e\"}\r\n";
}
}

View file

@ -0,0 +1,29 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:63724",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5223",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View file

@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging;
using Supercell.GUT.Titan.Debugging;
using Supercell.GUT.Titan.Logic.Debug;
namespace Supercell.GUT.Server.Debugging;
internal class ServerDebuggerListener : IDebuggerListener

View file

@ -1,6 +1,6 @@
using Microsoft.Extensions.Hosting;
using Supercell.GUT.Server.Network;
using Supercell.GUT.Titan.Debugging;
using Supercell.GUT.Titan.Logic.Debug;
namespace Supercell.GUT.Server;
internal class GUTServer : IHostedService

View file

@ -1,6 +1,6 @@
using Supercell.GUT.Logic;
using Supercell.GUT.Server.Protocol;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server.Network.Connection;
internal class ClientConnection

View file

@ -1,4 +1,4 @@
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server.Network.Connection;
internal interface IConnectionListener

View file

@ -9,8 +9,8 @@ using Supercell.GUT.Server.Network.Options;
using Supercell.GUT.Server.Network.Tcp;
using Supercell.GUT.Server.Protocol;
using Supercell.GUT.Server.Protocol.Extensions;
using Supercell.GUT.Titan.Debugging;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Debug;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server;

View file

@ -41,7 +41,26 @@ internal class AccountMessageHandler : MessageHandlerBase
{
AccountIdHigherInt = 0,
AccountIdLowerInt = 1,
SessionKey = "telegram_is_@BL4D3_BR43D"
SessionKey = "telegram_is_@BL4D3_BR34D"
});
}
[MessageHandler(10102)]
public async Task OnLoginUsingSession(LoginUsingSessionMessage loginUsingSessionMessage)
{
_logger.LogInformation("Logging account! sessionkey: {sk} | GameCenterId: {gcid} | GameVersion: {cgv} | account: ({h}-{l})",
loginUsingSessionMessage.SessionKey,
loginUsingSessionMessage.GamecenterId,
loginUsingSessionMessage.ClientGameVersion,
loginUsingSessionMessage.AccountIdHigherInt,
loginUsingSessionMessage.AccountIdLowerInt);
await _connection.SendMessage(new LoginOkMessage()
{
PrimaryAvatarIdHigherInt = loginUsingSessionMessage.AccountIdHigherInt,
PrimaryAvatarIdLowerInt = loginUsingSessionMessage.AccountIdLowerInt,
Fingerprint = "fece25cfc941db1a5bb3e79d4e6a60c34659f49e"
});
}
}

View file

@ -0,0 +1,42 @@
using Microsoft.Extensions.Logging;
using Supercell.GUT.Logic.Avatar;
using Supercell.GUT.Logic.Message.Avatar;
using Supercell.GUT.Server.Network.Connection;
using Supercell.GUT.Server.Protocol.Attributes;
using Supercell.GUT.Titan.Logic.Math;
namespace Supercell.GUT.Server.Protocol.Handlers;
[ServiceNode(3)]
internal class AvatarMessageHandler : MessageHandlerBase
{
private readonly ILogger _logger;
private readonly ClientConnection _connection;
public AvatarMessageHandler(ClientConnection connection, ILogger<AvatarMessageHandler> logger)
{
_logger = logger;
_connection = connection;
}
[MessageHandler(10201)]
public async Task OnSelectAvatar(SelectAvatarMessage selectAvatarMessage)
{
_logger.LogInformation("selecting avatar! avatar: ({h}-{l})",
selectAvatarMessage.AvatarIdHigherInt,
selectAvatarMessage.AvatarIdLowerInt);
await _connection.SendMessage(new AvatarDataMessage()
{
LogicClientAvatar = new LogicClientAvatar()
{
Id = new LogicLong(selectAvatarMessage.AvatarIdHigherInt, selectAvatarMessage.AvatarIdLowerInt),
Name = "BreadDEV",
AvatarCode = "a1",
TutorialFlags = 999999
}
});
}
}

View file

@ -1,7 +1,7 @@
using System.Collections.Immutable;
using System.Reflection;
using Supercell.GUT.Server.Protocol.Attributes;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server.Protocol.Handlers;
internal abstract class MessageHandlerBase

View file

@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Supercell.GUT.Server.Protocol.Attributes;
using Supercell.GUT.Server.Protocol.Handlers;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server.Protocol;
internal class MessageManager

View file

@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging;
using Supercell.GUT.Server.Network.Connection;
using Supercell.GUT.Titan.Encryption;
using Supercell.GUT.Titan.Message;
using Supercell.GUT.Titan.Logic.Message;
namespace Supercell.GUT.Server.Protocol;
internal class Messaging : IConnectionListener
@ -73,7 +73,7 @@ internal class Messaging : IConnectionListener
{
if (message.ByteStream.Offset == 0) message.Encode();
byte[] encodingBytes = message.ByteStream.Buffer.Take(message.ByteStream.Offset).ToArray();
byte[] encodingBytes = message.ByteStream.ByteArray!.Take(message.ByteStream.Offset).ToArray();
_encrypter?.Encrypt(encodingBytes);

View file

@ -1,79 +0,0 @@
using Supercell.GUT.Titan.Math;
using System.Runtime.CompilerServices;
namespace Supercell.GUT.Titan.Encoding;
public class ChecksumEncoder
{
private int _checksum;
private int _snapshotChecksum;
public ChecksumEncoder()
{
IsChecksumEnabled = true;
}
public virtual bool IsCheckSumOnlyMode => true;
public virtual ChecksumEncoder WriteBoolean(bool value) => UpdateCheckSum(value ? 13 : 7);
public virtual ChecksumEncoder WriteByte(byte value) => UpdateCheckSum(value + 11);
public virtual ChecksumEncoder WriteShort(short value) => UpdateCheckSum(value + 19);
public virtual ChecksumEncoder WriteInt(int value) => UpdateCheckSum(value + 9);
public virtual void WriteLong(LogicLong value) => value.Encode(this);
public virtual ChecksumEncoder WriteString(string? value) =>
UpdateCheckSum(value != null ? value.Length + 28 : 27);
public virtual ChecksumEncoder WriteBytes(ReadOnlySpan<byte> value) =>
UpdateCheckSum(value.Length + 28);
public bool IsChecksumEnabled { get; private set; }
public int CheckSum => IsChecksumEnabled ? _checksum : _snapshotChecksum;
public ChecksumEncoder EnableCheckSum(bool enable)
{
if (!IsChecksumEnabled && enable)
{
_checksum = _snapshotChecksum;
}
else
{
_snapshotChecksum = _checksum;
}
IsChecksumEnabled = enable;
return this;
}
public ChecksumEncoder ResetCheckSum()
{
_checksum = 0;
return this;
}
public override bool Equals(object? obj)
{
ChecksumEncoder? otherEncoder = obj as ChecksumEncoder;
return otherEncoder?.CheckSum == CheckSum;
}
public override int GetHashCode()
{
// original: Debugger::error("ChecksumEncoder hashCode not designed");
return CheckSum;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ChecksumEncoder UpdateCheckSum(int value)
{
_checksum = value + Ror4(_checksum, 31);
return this;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Ror4(int v, int c) => v >> c | v << 32 - c;
}

View file

@ -1,302 +0,0 @@
using Supercell.GUT.Titan.Math;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using TextEncoding = System.Text.Encoding;
namespace Supercell.GUT.Titan.Encoding.Streamed;
public class ByteStream : ChecksumEncoder
{
public byte[] Buffer { get; set; }
private int _bitIndex;
private int _length;
public int Offset { get; set; }
public int Length => _length > 0 ? _length : Offset;
public ByteStream(byte[] buffer, int length)
{
Buffer = buffer;
_length = length;
}
public ByteStream(int capacity)
{
Buffer = new byte[capacity];
}
public ByteStream()
{
Buffer = new byte[10];
}
public void SetByteArray(byte[] buffer, int length)
{
Buffer = buffer;
_length = length;
}
public bool ReadBoolean()
{
if (_bitIndex == 0)
++Offset;
bool value = (Buffer[Offset - 1] & 1 << _bitIndex) != 0;
_bitIndex = _bitIndex + 1 & 7;
return value;
}
public byte ReadByte()
{
_bitIndex = 0;
return Buffer[Offset++];
}
public short ReadShort()
{
_bitIndex = 0;
short ret = BinaryPrimitives.ReadInt16BigEndian(Buffer.AsSpan()[Offset..]);
Offset += 2;
return ret;
}
public int ReadInt()
{
_bitIndex = 0;
int ret = BinaryPrimitives.ReadInt32BigEndian(Buffer.AsSpan()[Offset..]);
Offset += 4;
return ret;
}
public int ReadVInt()
{
_bitIndex = 0;
int value = 0;
byte byteValue = Buffer[Offset++];
if ((byteValue & 0x40) != 0)
{
value |= byteValue & 0x3F;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 6;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 13;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 20;
if ((byteValue & 0x80) != 0)
{
value |= ((_ = Buffer[Offset++]) & 0x7F) << 27;
return (int)(value | 0x80000000);
}
return (int)(value | 0xF8000000);
}
return (int)(value | 0xFFF00000);
}
return (int)(value | 0xFFFFE000);
}
return (int)(value | 0xFFFFFFC0);
}
value |= byteValue & 0x3F;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 6;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 13;
if ((byteValue & 0x80) != 0)
{
value |= ((byteValue = Buffer[Offset++]) & 0x7F) << 20;
if ((byteValue & 0x80) != 0)
{
value |= ((_ = Buffer[Offset++]) & 0x7F) << 27;
}
}
}
}
return value;
}
public LogicLong ReadLong()
{
LogicLong ll = new();
ll.Decode(this);
return ll;
}
public string? ReadString()
{
int length = ReadInt();
if (length is < 0 or > 900000)
return null;
else if (length == 0)
return string.Empty;
string ret = TextEncoding.UTF8.GetString(Buffer, Offset, length);
Offset += length;
return ret;
}
public string ReadStringReference()
{
int length = ReadInt();
if (length is <= 0 or > 900000) return string.Empty;
string ret = TextEncoding.UTF8.GetString(Buffer, Offset, length);
Offset += length;
return ret;
}
public byte[] ReadBytes(int length)
{
_bitIndex = 0;
byte[] ret = Buffer.Skip(Offset).Take(length).ToArray();
Offset += length;
return ret;
}
public override ChecksumEncoder WriteBoolean(bool value)
{
base.WriteBoolean(value);
if (_bitIndex == 0)
{
EnsureCapacity(1);
Buffer[Offset++] = 0;
}
Buffer[Offset - 1] |= (byte)(value ? 1 : 0);
_bitIndex = _bitIndex + 1 & 7;
return this;
}
public override ChecksumEncoder WriteByte(byte value)
{
base.WriteByte(value);
EnsureCapacity(1);
Buffer[Offset++] = value;
return this;
}
public override ChecksumEncoder WriteShort(short value)
{
base.WriteShort(value);
EnsureCapacity(2);
BinaryPrimitives.WriteInt16BigEndian(Buffer.AsSpan()[Offset..], value);
Offset += 2;
return this;
}
public override ChecksumEncoder WriteInt(int value)
{
base.WriteInt(value);
EnsureCapacity(4);
WriteIntToByteArray(value);
return this;
}
public override ChecksumEncoder WriteString(string? value)
{
base.WriteString(value);
if (value == null)
{
WriteIntToByteArray(-1);
return this;
}
int size = TextEncoding.UTF8.GetByteCount(value);
WriteIntToByteArray(size);
EnsureCapacity(size);
TextEncoding.UTF8.GetBytes(value, Buffer.AsSpan()[Offset..]);
Offset += size;
return this;
}
public override ChecksumEncoder WriteBytes(ReadOnlySpan<byte> value)
{
base.WriteBytes(value);
WriteIntToByteArray(value.Length);
EnsureCapacity(value.Length);
value.CopyTo(Buffer.AsSpan()[Offset..]);
Offset += value.Length;
return this;
}
public override bool IsCheckSumOnlyMode => false;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteIntToByteArray(int value)
{
EnsureCapacity(4);
BinaryPrimitives.WriteInt32BigEndian(Buffer.AsSpan()[Offset..], value);
Offset += 4;
}
public void EnsureCapacity(int capacity)
{
_bitIndex = 0;
int bufferLength = Buffer.Length;
if (Offset + capacity > bufferLength)
{
byte[] tmpBuffer = new byte[Buffer.Length + capacity + 100];
System.Buffer.BlockCopy(Buffer, 0, tmpBuffer, 0, bufferLength);
Buffer = tmpBuffer;
}
}
public bool IsAtEnd()
{
return Offset >= Buffer.Length;
}
public void ResetOffset()
{
this.Offset = 0;
}
public void Destruct()
{
;
}
}

View file

@ -0,0 +1,298 @@
using Supercell.GUT.Titan.Logic.Debug;
using Supercell.GUT.Titan.Logic.Math;
using Supercell.GUT.Titan.Logic.Util;
namespace Supercell.GUT.Titan.Logic.DataStream;
public class ByteStream : ChecksumEncoder
{
public int Offset { get; set; }
public int Length { get; set; }
public int BitIndex { get; set; }
public byte[]? ByteArray { get; set; }
public ByteStream() : base()
{
this.Offset = 0;
this.Length = 0;
this.BitIndex = 0;
this.ByteArray = new byte[10];
}
public void ResetOffset()
{
this.Offset = 0;
this.BitIndex = 0;
}
public int GetLength()
{
if (this.Offset < this.Length)
return this.Length;
return this.Offset;
}
public override bool IsCheckSumOnlyMode()
{
return false;
}
public void SetOffset(int offset)
{
this.Offset = offset;
this.BitIndex = 0;
}
public int GetOffset()
{
return this.Offset;
}
public override void WriteString(string? value)
{
base.WriteString(value);
if (value == null)
{
this.WriteIntToByteArray(-1);
}
else
{
byte[] bytes = LogicStringUtil.GetBytes(value);
int length = bytes.Length;
if (length <= 900000)
{
this.EnsureCapacity(length + 4);
this.WriteIntToByteArray(length);
Buffer.BlockCopy(bytes, 0, this.ByteArray!, this.Offset, length);
this.Offset += length;
}
else
{
Debugger.Warning("ByteStream::writeString invalid string length " + length);
this.WriteIntToByteArray(-1);
}
}
}
public void WriteIntToByteArray(int value)
{
this.EnsureCapacity(4);
this.BitIndex = 0;
this.ByteArray![this.Offset++] = (byte)(value >> 24);
this.ByteArray![this.Offset++] = (byte)(value >> 16);
this.ByteArray![this.Offset++] = (byte)(value >> 8);
this.ByteArray![this.Offset++] = (byte)value;
}
public string? ReadString()
{
int length = this.ReadInt();
if (length > -1)
{
if (length >= 900001)
{
Debugger.Error("Too long String encountered.");
}
string result = LogicStringUtil.CreateString(this.ByteArray!, this.Offset, length);
this.Offset += length;
return result;
}
else
{
if (length != -1)
Debugger.Error("Negative String length encountered.");
}
return null;
}
public override void WriteBoolean(bool value)
{
base.WriteBoolean(value);
if (this.BitIndex == 0)
{
this.EnsureCapacity(1);
this.ByteArray![this.Offset++] = 0;
}
if (value)
this.ByteArray![this.Offset - 1] |= (byte)(1 << this.BitIndex);
this.BitIndex = (this.BitIndex + 1) & 7;
}
public bool ReadBoolean()
{
if (this.BitIndex == 0)
++this.Offset;
bool value = (this.ByteArray![this.Offset - 1] & (1 << this.BitIndex)) != 0;
this.BitIndex = (this.BitIndex + 1) & 7;
return value;
}
public override void WriteInt(int value)
{
base.WriteInt(value);
this.WriteIntToByteArray(value);
}
public override void WriteByte(byte value)
{
base.WriteByte(value);
this.EnsureCapacity(1);
this.BitIndex = 0;
this.ByteArray![this.Offset++] = (byte)value;
}
public override void WriteShort(short value)
{
base.WriteShort(value);
this.EnsureCapacity(2);
this.BitIndex = 0;
this.ByteArray![this.Offset++] = (byte)(value >> 8);
this.ByteArray[this.Offset++] = (byte)value;
}
public int ReadInt()
{
this.BitIndex = 0;
return (this.ByteArray![this.Offset++] << 24) |
(this.ByteArray[this.Offset++] << 16) |
(this.ByteArray[this.Offset++] << 8) |
this.ByteArray[this.Offset++];
}
public byte ReadByte()
{
this.BitIndex = 0;
return this.ByteArray![this.Offset++];
}
public short ReadShort()
{
this.BitIndex = 0;
return (short)((this.ByteArray![this.Offset++] << 8) |
this.ByteArray[this.Offset++]);
}
public LogicLong ReadLong()
{
return this.ReadLong(null);
}
public LogicLong ReadLong(LogicLong? logicLong)
{
LogicLong? v2 = logicLong;
if (logicLong == null)
v2 = new LogicLong();
v2!.Decode(this);
return v2;
}
public override void WriteBytes(byte[]? value, int length)
{
base.WriteBytes(value, length);
if (value == null)
{
this.WriteIntToByteArray(-1);
}
else
{
this.EnsureCapacity(length + 4);
this.WriteIntToByteArray(length);
Buffer.BlockCopy(value, 0, this.ByteArray!, this.Offset, length);
this.Offset += length;
}
}
public int ReadBytesLength()
{
return this.ReadInt();
}
public byte[]? ReadBytes(int length)
{
this.BitIndex = 0;
if (length > -1)
{
byte[] array = new byte[length];
Buffer.BlockCopy(this.ByteArray!, this.Offset, array, 0, length);
this.Offset += length;
return array;
}
else
{
if (length != -1)
Debugger.Error("Negative readBytes length encountered.");
}
return null;
}
public void SetByteArray(byte[] byteArray, int length)
{
this.Offset = 0;
this.Length = length;
this.BitIndex = 0;
this.ByteArray = byteArray;
}
public override void Destruct()
{
this.Offset = 0;
this.Length = 0;
this.BitIndex = 0;
this.ByteArray = null;
}
public bool IsAtEnd()
{
return this.Offset >= this.Length;
}
public byte GetDataPointer()
{
return this.ByteArray![this.Offset];
}
private void EnsureCapacity(int capacity)
{
int bufferLength = this.ByteArray!.Length;
if (this.Offset + capacity > bufferLength)
{
byte[] tmpBuffer = new byte[this.ByteArray.Length + capacity + 100];
Buffer.BlockCopy(this.ByteArray, 0, tmpBuffer, 0, bufferLength);
this.ByteArray = tmpBuffer;
}
}
}

View file

@ -0,0 +1,98 @@
using Supercell.GUT.Titan.Logic.Math;
namespace Supercell.GUT.Titan.Logic.DataStream;
public class ChecksumEncoder
{
public int CheckSum { get; set; }
public int SnapshotCheckSum { get; set; }
public bool IsChecksumEnabled { get; set; }
public ChecksumEncoder()
{
this.CheckSum = 0;
this.SnapshotCheckSum = 0;
this.IsChecksumEnabled = true;
}
public virtual bool IsCheckSumOnlyMode()
{
return true;
}
public virtual void WriteString(string? value)
{
int v2 = (this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum);
if (value != null)
this.CheckSum = value.Length + v2 + 28;
else
this.CheckSum = v2 + 0x1B;
}
public virtual void WriteBoolean(bool value)
{
int v2 = 7;
if (value)
v2 = 13;
this.CheckSum = ((this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum)) + v2;
}
public virtual void WriteInt(int value)
{
this.CheckSum = ((this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum)) + value + 9;
}
public virtual void WriteByte(byte value)
{
this.CheckSum = ((this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum)) + value + 11;
}
public virtual void WriteShort(short value)
{
this.CheckSum = ((this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum)) + value + 19;
}
public virtual void WriteBytes(byte[]? value, int length)
{
int v3 = (this.CheckSum >> 0x1F) & 0x7FFFFFFF | (2 * this.CheckSum);
if (value != null)
this.CheckSum = length + v3 + 28;
else
this.CheckSum = v3 + 0x1B;
}
public virtual void WriteLong(LogicLong logicLong)
{
logicLong.Encode(this);
}
public override bool Equals(object? obj)
{
if (obj != null && obj is ChecksumEncoder checksumEncoder)
{
bool v4 = this.IsChecksumEnabled;
int v5 = checksumEncoder.CheckSum;
bool v6 = checksumEncoder.IsChecksumEnabled;
int v7 = checksumEncoder.SnapshotCheckSum;
if (!v6)
v5 = v7;
int v8 = this.CheckSum;
int v9 = this.SnapshotCheckSum;
int v10 = v5;
if (!v4)
v8 = v9;
if (v8 == v10)
return true;
}
return false;
}
public virtual void Destruct()
{
this.CheckSum = 0;
this.SnapshotCheckSum = 0;
this.IsChecksumEnabled = true;
}
}

View file

@ -1,4 +1,5 @@
namespace Supercell.GUT.Titan.Debugging;
namespace Supercell.GUT.Titan.Logic.Debug;
public static class Debugger
{
private static IDebuggerListener? _listener;

View file

@ -1,4 +1,5 @@
namespace Supercell.GUT.Titan.Debugging;
namespace Supercell.GUT.Titan.Logic.Debug;
public interface IDebuggerListener
{
void OnPrint(string log);

View file

@ -1,8 +1,9 @@
namespace Supercell.GUT.Titan.Debugging;
namespace Supercell.GUT.Titan.Logic.Debug;
public class LogicException : Exception
{
public LogicException(string message) : base(message)
{
// LogicException.
;
}
}

View file

@ -1,7 +1,6 @@
using Supercell.GUT.Titan.Encoding;
using Supercell.GUT.Titan.Encoding.Streamed;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Titan.Math;
namespace Supercell.GUT.Titan.Logic.Math;
public class LogicLong
{

View file

@ -1,4 +1,4 @@
namespace Supercell.GUT.Titan.Math;
namespace Supercell.GUT.Titan.Logic.Math;
public static class LogicMath
{

View file

@ -1,4 +1,4 @@
namespace Supercell.GUT.Titan.Math;
namespace Supercell.GUT.Titan.Logic.Math;
public class LogicRandom
{

View file

@ -1,4 +1,4 @@
namespace Supercell.GUT.Titan.Message;
namespace Supercell.GUT.Titan.Logic.Message;
public abstract class LogicMessageFactory
{

View file

@ -1,6 +1,6 @@
using Supercell.GUT.Titan.Encoding.Streamed;
using Supercell.GUT.Titan.Logic.DataStream;
namespace Supercell.GUT.Titan.Message;
namespace Supercell.GUT.Titan.Logic.Message;
public abstract class PiranhaMessage
{

View file

@ -1,4 +1,4 @@
namespace Supercell.GUT.Titan.Message;
namespace Supercell.GUT.Titan.Logic.Message;
public abstract class VersionedMessage : PiranhaMessage
{

View file

@ -0,0 +1,131 @@
using Supercell.GUT.Titan.Logic.Debug;
namespace Supercell.GUT.Titan.Logic.Util;
public class LogicArrayList<T>
{
private T[] m_items;
private int m_size;
public LogicArrayList()
{
this.m_items = Array.Empty<T>();
}
public LogicArrayList(int capacity)
{
this.m_items = new T[capacity];
}
public T this[int index]
{
get
{
if (this.m_size <= index)
{
Debugger.Error($"LogicArrayList.get out of bounds {index}/{this.m_size}");
}
return this.m_items[index];
}
set
{
if (this.m_size <= index)
{
Debugger.Error($"LogicArrayList.set out of bounds {index}/{this.m_size}");
}
this.m_items[index] = value;
}
}
public void Add(T item)
{
int size = this.m_items.Length;
if (size == m_size)
{
this.EnsureCapacity(size != 0 ? size * 2 : 5);
}
this.m_items[this.m_size++] = item;
}
public void Add(int index, T item)
{
int size = this.m_items.Length;
if (size == this.m_size)
{
this.EnsureCapacity(size != 0 ? size * 2 : 5);
}
if (this.m_size > index)
{
Array.Copy(this.m_items, index, this.m_items, index + 1, this.m_size - index);
}
this.m_items[index] = item;
this.m_size += 1;
}
public void AddAll(LogicArrayList<T> array)
{
this.EnsureCapacity(this.m_size + array.m_size);
for (int i = 0, cnt = array.m_size; i < cnt; i++)
{
this.m_items[this.m_size++] = array[i];
}
}
public int IndexOf(T item)
{
return Array.IndexOf(this.m_items, item, 0, this.m_size);
}
public T Remove(int index)
{
T item = default;
if ((uint)index < m_size)
{
item = this.m_items[index];
this.m_size -= 1;
if (index != m_size)
{
Array.Copy(this.m_items, index + 1, this.m_items, index, this.m_size - index);
}
}
return item;
}
public void EnsureCapacity(int count)
{
int size = this.m_items.Length;
if (size < count)
{
Array.Resize(ref this.m_items, count);
}
}
public int Size()
{
return this.m_size;
}
public void Clear()
{
this.m_size = 0;
}
public void Destruct()
{
this.m_items = null;
this.m_size = 0;
}
}

View file

@ -0,0 +1,30 @@
using System.Text;
namespace Supercell.GUT.Titan.Logic.Util;
public static class LogicStringUtil
{
public static string SafeString(string a1, string? a2, string a3)
{
if (a2 != null)
{
a1 = a2;
}
else
{
a1 = a3;
}
return a1;
}
public static string CreateString(byte[] byteArray, int offset, int length)
{
return Encoding.UTF8.GetString(byteArray, offset, length);
}
public static byte[] GetBytes(string value)
{
return Encoding.UTF8.GetBytes(value);
}
}

View file

@ -1,18 +0,0 @@
namespace Supercell.GUT.Titan.Util;
public static class LogicStringUtil
{
public static string SafeString(string a1, string? a2, string a3)
{
if (a2 != null)
{
a1 = a2;
}
else
{
a1 = a3;
}
return a1;
}
}

View file

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Supercell.GUT.Titan", "Supe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Supercell.GUT.Logic", "Supercell.GUT.Logic\Supercell.GUT.Logic.csproj", "{4441B345-1B99-4DE6-9764-B34E3ED8A982}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Supercell.GUT.SDK", "Supercell.GUT.SDK\Supercell.GUT.SDK.csproj", "{CB2AD800-4FD4-4F84-8BFD-6791CC0CDCC6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{4441B345-1B99-4DE6-9764-B34E3ED8A982}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4441B345-1B99-4DE6-9764-B34E3ED8A982}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4441B345-1B99-4DE6-9764-B34E3ED8A982}.Release|Any CPU.Build.0 = Release|Any CPU
{CB2AD800-4FD4-4F84-8BFD-6791CC0CDCC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB2AD800-4FD4-4F84-8BFD-6791CC0CDCC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB2AD800-4FD4-4F84-8BFD-6791CC0CDCC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB2AD800-4FD4-4F84-8BFD-6791CC0CDCC6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE