mirror of
https://github.com/thebreaddev/Supercell.GUT.git
synced 2024-11-24 21:34:38 +00:00
[v0.1.0] database implementation
not finished. early wip state
This commit is contained in:
parent
8c6a533918
commit
281d2789ea
24 changed files with 637 additions and 29 deletions
|
@ -72,4 +72,9 @@ public class LogicClientAvatar : LogicBase
|
|||
|
||||
checksumEncoder.WriteInt(this.TutorialFlags);
|
||||
}
|
||||
|
||||
public void SetTutorialFlags(int tutorialFlags)
|
||||
{
|
||||
this.TutorialFlags |= tutorialFlags;
|
||||
}
|
||||
}
|
||||
|
|
46
Supercell.GUT.Logic/Message/Account/CreateAvatarMessage.cs
Normal file
46
Supercell.GUT.Logic/Message/Account/CreateAvatarMessage.cs
Normal file
|
@ -0,0 +1,46 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Account;
|
||||
|
||||
[VersionedMessage(10200)]
|
||||
public class CreateAvatarMessage : VersionedMessage
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
|
||||
public CreateAvatarMessage() : base(0)
|
||||
{
|
||||
Name = null;
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
|
||||
ByteStream.WriteString(Name);
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
|
||||
Name = ByteStream.ReadString();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 10200;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override void Destruct()
|
||||
{
|
||||
base.Destruct();
|
||||
|
||||
Name = null;
|
||||
}
|
||||
}
|
33
Supercell.GUT.Logic/Message/Account/KeepAliveMessage.cs
Normal file
33
Supercell.GUT.Logic/Message/Account/KeepAliveMessage.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Account;
|
||||
|
||||
[VersionedMessage(10108)]
|
||||
public class KeepAliveMessage : VersionedMessage
|
||||
{
|
||||
public KeepAliveMessage() : base(0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 10108;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
42
Supercell.GUT.Logic/Message/Avatar/AddableFriendsMessage.cs
Normal file
42
Supercell.GUT.Logic/Message/Avatar/AddableFriendsMessage.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Avatar;
|
||||
|
||||
[VersionedMessage(20107)]
|
||||
public class AddableFriendsMessage : VersionedMessage
|
||||
{
|
||||
public AddableFriendsMessage() : base(0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
|
||||
this.ByteStream.WriteInt(-1);
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
|
||||
this.ByteStream.ReadInt();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 20107;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public override void Destruct()
|
||||
{
|
||||
base.Destruct();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
using Supercell.GUT.Titan.Logic.Util;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Avatar;
|
||||
|
||||
[VersionedMessage(10503)]
|
||||
public class AskForAddableFriendsMessage : VersionedMessage
|
||||
{
|
||||
public LogicArrayList<string> FacebookIds { get; set; }
|
||||
public LogicArrayList<string> GamecenterIds { get; set; }
|
||||
|
||||
public AskForAddableFriendsMessage() : base(0)
|
||||
{
|
||||
this.FacebookIds = new LogicArrayList<string>();
|
||||
this.GamecenterIds = new LogicArrayList<string>();
|
||||
}
|
||||
|
||||
public override void Destruct()
|
||||
{
|
||||
base.Destruct();
|
||||
|
||||
this.FacebookIds.Clear();
|
||||
this.GamecenterIds.Clear();
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
|
||||
int size = this.FacebookIds.Size();
|
||||
|
||||
this.ByteStream.WriteInt(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
this.ByteStream.WriteString(this.FacebookIds[i]);
|
||||
}
|
||||
|
||||
size = this.GamecenterIds.Size();
|
||||
|
||||
this.ByteStream.WriteInt(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
this.ByteStream.WriteString(this.GamecenterIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 10503;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Avatar;
|
||||
|
||||
[VersionedMessage(10504)]
|
||||
public class AskForFriendListMessage : VersionedMessage
|
||||
{
|
||||
public AskForFriendListMessage() : base(0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 10504;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
37
Supercell.GUT.Logic/Message/Avatar/FriendListMessage.cs
Normal file
37
Supercell.GUT.Logic/Message/Avatar/FriendListMessage.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Avatar;
|
||||
|
||||
[VersionedMessage(20105)]
|
||||
public class FriendListMessage : VersionedMessage
|
||||
{
|
||||
public FriendListMessage() : base(0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
|
||||
this.ByteStream.WriteInt(-1);
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
|
||||
this.ByteStream.ReadInt();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 20105;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using Supercell.GUT.Logic.Message.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
namespace Supercell.GUT.Logic.Message.Avatar;
|
||||
|
||||
[VersionedMessage(10210)]
|
||||
public class TutorialProgressUpdateMessage : VersionedMessage
|
||||
{
|
||||
public int TutorialFlags { get; set; }
|
||||
|
||||
public TutorialProgressUpdateMessage() : base(0)
|
||||
{
|
||||
TutorialFlags = 0;
|
||||
}
|
||||
|
||||
public override void Destruct()
|
||||
{
|
||||
base.Destruct();
|
||||
|
||||
TutorialFlags = 0;
|
||||
}
|
||||
|
||||
public override void Encode()
|
||||
{
|
||||
base.Encode();
|
||||
|
||||
ByteStream.WriteInt(TutorialFlags);
|
||||
}
|
||||
|
||||
public override void Decode()
|
||||
{
|
||||
base.Decode();
|
||||
|
||||
TutorialFlags = ByteStream.ReadInt();
|
||||
}
|
||||
|
||||
public override int GetMessageType()
|
||||
{
|
||||
return 10210;
|
||||
}
|
||||
|
||||
public override int GetServiceNodeType()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
54
Supercell.GUT.Server/Database/DatabaseManager.cs
Normal file
54
Supercell.GUT.Server/Database/DatabaseManager.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using Supercell.GUT.Server.Database.Document;
|
||||
using Supercell.GUT.Server.Database.Options;
|
||||
|
||||
namespace Supercell.GUT.Server.Database;
|
||||
|
||||
public class DatabaseManager
|
||||
{
|
||||
private const string IdentifierCounterCollection = "t_id_counter";
|
||||
private static readonly FindOneAndUpdateOptions<IdentifierCounterDocument> s_counterUpdateOptions = new() { ReturnDocument = ReturnDocument.After };
|
||||
|
||||
private readonly DatabaseOptions _options;
|
||||
|
||||
private readonly MongoClient _client;
|
||||
private readonly IMongoDatabase _database;
|
||||
|
||||
private readonly IMongoCollection<IdentifierCounterDocument> _idCounters;
|
||||
|
||||
public DatabaseManager(IOptions<DatabaseOptions> options)
|
||||
{
|
||||
_options = options.Value;
|
||||
|
||||
_client = new MongoClient(_options.MongoConnectionString);
|
||||
_database = _client.GetDatabase(_options.DatabaseName);
|
||||
|
||||
_idCounters = _database.GetCollection<IdentifierCounterDocument>(IdentifierCounterCollection);
|
||||
}
|
||||
|
||||
public IMongoCollection<TDatabaseDocument> GetCollection<TDatabaseDocument>(string collectionName) where TDatabaseDocument : IDatabaseDocument
|
||||
{
|
||||
return _database.GetCollection<TDatabaseDocument>(collectionName);
|
||||
}
|
||||
|
||||
public async Task<int> GetNextLowIdAsync(string counterName)
|
||||
{
|
||||
var cursor = await _idCounters.FindAsync(doc => doc.CounterName == counterName);
|
||||
if (!cursor.Any())
|
||||
{
|
||||
await _idCounters.InsertOneAsync(new IdentifierCounterDocument
|
||||
{
|
||||
CounterName = counterName,
|
||||
CurrentLowId = 0
|
||||
});
|
||||
}
|
||||
|
||||
IdentifierCounterDocument? document = await _idCounters.FindOneAndUpdateAsync<IdentifierCounterDocument>(
|
||||
x => x.CounterName == counterName,
|
||||
Builders<IdentifierCounterDocument>.Update.Inc(nameof(IdentifierCounterDocument.CurrentLowId), 1),
|
||||
s_counterUpdateOptions);
|
||||
|
||||
return document.CurrentLowId;
|
||||
}
|
||||
}
|
19
Supercell.GUT.Server/Database/Document/AccountDocument.cs
Normal file
19
Supercell.GUT.Server/Database/Document/AccountDocument.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using Supercell.GUT.Titan.Logic.Math;
|
||||
|
||||
namespace Supercell.GUT.Server.Database.Document;
|
||||
public class AccountDocument : MongoSerializeableBase, IDatabaseDocument
|
||||
{
|
||||
public LogicLong DocumentId { get; set; }
|
||||
public string SessionKey { get; set; } = string.Empty;
|
||||
|
||||
public AccountDocument()
|
||||
{
|
||||
DocumentId = new();
|
||||
}
|
||||
|
||||
public AccountDocument(LogicLong id, string token)
|
||||
{
|
||||
DocumentId = id;
|
||||
SessionKey = token;
|
||||
}
|
||||
}
|
28
Supercell.GUT.Server/Database/Document/AvatarDocument.cs
Normal file
28
Supercell.GUT.Server/Database/Document/AvatarDocument.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Supercell.GUT.Logic.Avatar;
|
||||
using Supercell.GUT.Titan.Logic.Math;
|
||||
|
||||
namespace Supercell.GUT.Server.Database.Document;
|
||||
|
||||
public class AvatarDocument : MongoSerializeableBase, IDatabaseDocument
|
||||
{
|
||||
public LogicLong DocumentId { get; set; }
|
||||
|
||||
public LogicClientAvatar LogicClientAvatar { get; set; } = new();
|
||||
|
||||
public int LastSaveTime { get; set; }
|
||||
|
||||
public AvatarDocument()
|
||||
{
|
||||
DocumentId = new();
|
||||
}
|
||||
|
||||
public AvatarDocument(LogicLong id)
|
||||
{
|
||||
DocumentId = id;
|
||||
}
|
||||
|
||||
public void SetId(LogicLong id)
|
||||
{
|
||||
LogicClientAvatar.Id = id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
using Supercell.GUT.Titan.Logic.Math;
|
||||
|
||||
namespace Supercell.GUT.Server.Database.Document;
|
||||
|
||||
public interface IDatabaseDocument
|
||||
{
|
||||
LogicLong DocumentId { get; set; }
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Supercell.GUT.Server.Database.Document;
|
||||
|
||||
internal class IdentifierCounterDocument : MongoSerializeableBase
|
||||
{
|
||||
public string CounterName { get; set; } = string.Empty;
|
||||
public int CurrentLowId { get; set; }
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Supercell.GUT.Server.Database.Document;
|
||||
|
||||
public abstract class MongoSerializeableBase
|
||||
{
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.ObjectId)]
|
||||
[JsonIgnore]
|
||||
public string? MongoId { get; set; }
|
||||
}
|
7
Supercell.GUT.Server/Database/Options/DatabaseOptions.cs
Normal file
7
Supercell.GUT.Server/Database/Options/DatabaseOptions.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Supercell.GUT.Server.Database.Options;
|
||||
|
||||
public class DatabaseOptions
|
||||
{
|
||||
public required string MongoConnectionString { get; set; }
|
||||
public required string DatabaseName { get; set; }
|
||||
}
|
86
Supercell.GUT.Server/Document/DocumentManager.cs
Normal file
86
Supercell.GUT.Server/Document/DocumentManager.cs
Normal file
|
@ -0,0 +1,86 @@
|
|||
using MongoDB.Driver;
|
||||
using Supercell.GUT.Server.Database;
|
||||
using Supercell.GUT.Server.Database.Document;
|
||||
using Supercell.GUT.Server.Util;
|
||||
using Supercell.GUT.Titan.Logic.Math;
|
||||
|
||||
namespace Supercell.GUT.Server.Document;
|
||||
|
||||
internal class DocumentManager
|
||||
{
|
||||
private const string AccountCollectionName = "t_account_info";
|
||||
private const string AvatarCollectionName = "t_player_avatar";
|
||||
|
||||
private const string AccountIdCounterName = "AccountId";
|
||||
|
||||
private readonly DatabaseManager _databaseManager;
|
||||
|
||||
public LogicLong Id { get; private set; } = new();
|
||||
|
||||
public AccountDocument? AccountDocument { get; private set; }
|
||||
public AvatarDocument? AvatarDocument { get; private set; }
|
||||
|
||||
public DocumentManager(DatabaseManager databaseManager)
|
||||
{
|
||||
_databaseManager = databaseManager;
|
||||
}
|
||||
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
if (AccountDocument != null)
|
||||
{
|
||||
IMongoCollection<AccountDocument> accountCollection = _databaseManager.GetCollection<AccountDocument>(AccountCollectionName);
|
||||
await accountCollection.ReplaceOneAsync(doc => doc.DocumentId.Equals(AccountDocument.DocumentId), AccountDocument);
|
||||
}
|
||||
|
||||
if (AvatarDocument != null)
|
||||
{
|
||||
AvatarDocument.LastSaveTime = TimeUtil.GetCurrentTimestamp();
|
||||
|
||||
IMongoCollection<AvatarDocument> avatarCollection = _databaseManager.GetCollection<AvatarDocument>(AvatarCollectionName);
|
||||
await avatarCollection.ReplaceOneAsync(doc => doc.DocumentId.Equals(AvatarDocument.DocumentId), AvatarDocument);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateAccount()
|
||||
{
|
||||
if (AccountDocument != null) throw new InvalidOperationException("DocumentManager::CreateAccount: called when AccountDocument already created!");
|
||||
|
||||
int lowId = await _databaseManager.GetNextLowIdAsync(AccountIdCounterName);
|
||||
|
||||
AccountDocument = new(new(0, lowId), "ToDoRandomToken");
|
||||
IMongoCollection<AccountDocument> accountCollection = _databaseManager.GetCollection<AccountDocument>(AccountCollectionName);
|
||||
|
||||
await accountCollection.InsertOneAsync(AccountDocument);
|
||||
Id = AccountDocument.DocumentId;
|
||||
}
|
||||
|
||||
public async Task EnsureAccountDocument()
|
||||
{
|
||||
if (AccountDocument != null) return;
|
||||
|
||||
IMongoCollection<AccountDocument> accountCollection = _databaseManager.GetCollection<AccountDocument>(AccountCollectionName);
|
||||
AccountDocument = await (await accountCollection.FindAsync(document => document.DocumentId.Equals(Id))).SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task EnsureAvatarDocument()
|
||||
{
|
||||
if (AvatarDocument != null) return;
|
||||
|
||||
IMongoCollection<AvatarDocument> avatarCollection = _databaseManager.GetCollection<AvatarDocument>(AvatarCollectionName);
|
||||
AvatarDocument = await (await avatarCollection.FindAsync(document => document.DocumentId.Equals(Id))).SingleOrDefaultAsync();
|
||||
|
||||
if (AvatarDocument == null)
|
||||
{
|
||||
AvatarDocument = new(Id);
|
||||
await avatarCollection.InsertOneAsync(AvatarDocument);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDocumentId(LogicLong id)
|
||||
{
|
||||
if (Id.LowerInt > 0) throw new InvalidOperationException("DocumentManager::SetDocumentId: trying to override Id.");
|
||||
|
||||
Id = id;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Supercell.GUT.Logic;
|
||||
using Supercell.GUT.Logic.Avatar;
|
||||
using Supercell.GUT.Server.Protocol;
|
||||
using Supercell.GUT.Titan.Logic.Message;
|
||||
|
||||
|
@ -11,6 +12,8 @@ internal class ClientConnection
|
|||
private readonly IConnectionListener _listener;
|
||||
private readonly MessageManager _messageManager;
|
||||
|
||||
public LogicClientAvatar? LogicClientAvatar { get; set; }
|
||||
|
||||
private readonly byte[] _receiveBuffer;
|
||||
private IProtocolEntity? _protocolEntity;
|
||||
private DateTime _lastKeepAliveTime;
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Supercell.GUT.Logic.Message;
|
||||
using Supercell.GUT.Server.Database;
|
||||
using Supercell.GUT.Server.Database.Options;
|
||||
using Supercell.GUT.Server.Debugging;
|
||||
using Supercell.GUT.Server.Document;
|
||||
using Supercell.GUT.Server.Network;
|
||||
using Supercell.GUT.Server.Network.Connection;
|
||||
using Supercell.GUT.Server.Network.Options;
|
||||
|
@ -17,6 +20,7 @@ namespace Supercell.GUT.Server;
|
|||
internal static class Program
|
||||
{
|
||||
private const string GatewayOptionsSection = "Gateway";
|
||||
private const string DatabaseOptionsSection = "Database";
|
||||
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
|
@ -25,6 +29,7 @@ internal static class Program
|
|||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
builder.Services.Configure<GatewayOptions>(builder.Configuration.GetRequiredSection(GatewayOptionsSection));
|
||||
builder.Services.Configure<DatabaseOptions>(builder.Configuration.GetRequiredSection(DatabaseOptionsSection));
|
||||
|
||||
builder.Services.AddHandlers();
|
||||
builder.Services.AddSingleton<IDebuggerListener, ServerDebuggerListener>();
|
||||
|
@ -34,6 +39,8 @@ internal static class Program
|
|||
builder.Services.AddScoped<IConnectionListener, Messaging>();
|
||||
builder.Services.AddSingleton<LogicMessageFactory, GUTMessageFactory>();
|
||||
builder.Services.AddScoped<MessageManager>();
|
||||
builder.Services.AddScoped<DocumentManager>();
|
||||
builder.Services.AddSingleton<DatabaseManager>();
|
||||
|
||||
builder.Services.AddHostedService<GUTServer>();
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Supercell.GUT.Logic.Message.Account;
|
||||
using Supercell.GUT.Server.Database.Document;
|
||||
using Supercell.GUT.Server.Document;
|
||||
using Supercell.GUT.Server.Network.Connection;
|
||||
using Supercell.GUT.Server.Protocol.Attributes;
|
||||
|
||||
|
@ -10,11 +12,19 @@ internal class AccountMessageHandler : MessageHandlerBase
|
|||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ClientConnection _connection;
|
||||
private readonly DocumentManager _documentManager;
|
||||
|
||||
public AccountMessageHandler(ClientConnection connection, ILogger<AccountMessageHandler> logger)
|
||||
public AccountMessageHandler(ClientConnection connection, ILogger<AccountMessageHandler> logger, DocumentManager documentManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_connection = connection;
|
||||
_documentManager = documentManager;
|
||||
}
|
||||
|
||||
[MessageHandler(10108)]
|
||||
public async Task OnKeepAlive(KeepAliveMessage keepAliveMessage)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
[MessageHandler(10105)]
|
||||
|
@ -33,32 +43,59 @@ internal class AccountMessageHandler : MessageHandlerBase
|
|||
[MessageHandler(10103)]
|
||||
public async Task OnCreateAccount(CreateAccountMessage createAccountMessage)
|
||||
{
|
||||
_logger.LogInformation("Creating account! FacebookId: {fid} | GameCenterId: {gcid}",
|
||||
createAccountMessage.FacebookId,
|
||||
createAccountMessage.GameCenterId);
|
||||
await _documentManager.CreateAccount();
|
||||
|
||||
AccountDocument? accountDocument = _documentManager.AccountDocument;
|
||||
if (accountDocument == null)
|
||||
{
|
||||
await _connection.SendMessage(new CreateAccountFailedMessage()
|
||||
{
|
||||
ErrorCode = 1
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await _connection.SendMessage(new CreateAccountOkMessage()
|
||||
{
|
||||
AccountIdHigherInt = 0,
|
||||
AccountIdLowerInt = 1,
|
||||
SessionKey = "telegram_is_@BL4D3_BR34D"
|
||||
AccountIdHigherInt = accountDocument.DocumentId.HigherInt,
|
||||
AccountIdLowerInt = accountDocument.DocumentId.LowerInt,
|
||||
SessionKey = accountDocument.SessionKey
|
||||
});
|
||||
}
|
||||
|
||||
[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);
|
||||
if (_documentManager.Id.LowerInt == 0)
|
||||
_documentManager.SetDocumentId(new (loginUsingSessionMessage.AccountIdHigherInt, loginUsingSessionMessage.AccountIdLowerInt));
|
||||
|
||||
await _documentManager.EnsureAccountDocument();
|
||||
|
||||
AccountDocument? accountDocument = _documentManager.AccountDocument;
|
||||
if (accountDocument == null)
|
||||
{
|
||||
await _connection.SendMessage(new LoginFailedMessage()
|
||||
{
|
||||
ErrorCode = 2
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
else if (accountDocument.SessionKey != loginUsingSessionMessage.SessionKey)
|
||||
{
|
||||
await _connection.SendMessage(new LoginFailedMessage()
|
||||
{
|
||||
ErrorCode = 5
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await _connection.SendMessage(new LoginOkMessage()
|
||||
{
|
||||
PrimaryAvatarIdHigherInt = loginUsingSessionMessage.AccountIdHigherInt,
|
||||
PrimaryAvatarIdLowerInt = loginUsingSessionMessage.AccountIdLowerInt,
|
||||
PrimaryAvatarIdHigherInt = accountDocument.DocumentId.HigherInt,
|
||||
PrimaryAvatarIdLowerInt = accountDocument.DocumentId.LowerInt,
|
||||
|
||||
Fingerprint = "fece25cfc941db1a5bb3e79d4e6a60c34659f49e"
|
||||
});
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Supercell.GUT.Logic.Avatar;
|
||||
using Supercell.GUT.Logic.Message.Avatar;
|
||||
using Supercell.GUT.Server.Document;
|
||||
using Supercell.GUT.Server.Network.Connection;
|
||||
using Supercell.GUT.Server.Protocol.Attributes;
|
||||
using Supercell.GUT.Titan.Logic.Math;
|
||||
|
||||
namespace Supercell.GUT.Server.Protocol.Handlers;
|
||||
|
||||
|
@ -12,31 +12,52 @@ internal class AvatarMessageHandler : MessageHandlerBase
|
|||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ClientConnection _connection;
|
||||
private readonly DocumentManager _documentManager;
|
||||
|
||||
public AvatarMessageHandler(ClientConnection connection, ILogger<AvatarMessageHandler> logger)
|
||||
public AvatarMessageHandler(ClientConnection connection, ILogger<AvatarMessageHandler> logger, DocumentManager documentManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_connection = connection;
|
||||
_documentManager = documentManager;
|
||||
}
|
||||
|
||||
[MessageHandler(10201)]
|
||||
public async Task OnSelectAvatar(SelectAvatarMessage selectAvatarMessage)
|
||||
{
|
||||
_logger.LogInformation("selecting avatar! avatar: ({h}-{l})",
|
||||
selectAvatarMessage.AvatarIdHigherInt,
|
||||
selectAvatarMessage.AvatarIdLowerInt);
|
||||
await _documentManager.EnsureAvatarDocument();
|
||||
LogicClientAvatar logicClientAvatar = _documentManager.AvatarDocument!.LogicClientAvatar;
|
||||
|
||||
if (logicClientAvatar.Id.LowerInt == 0)
|
||||
{
|
||||
_documentManager.AvatarDocument.SetId(_documentManager.AvatarDocument.DocumentId);
|
||||
await _documentManager.SaveAsync();
|
||||
}
|
||||
|
||||
_connection.LogicClientAvatar = logicClientAvatar;
|
||||
|
||||
await _connection.SendMessage(new AvatarDataMessage()
|
||||
{
|
||||
LogicClientAvatar = new LogicClientAvatar()
|
||||
{
|
||||
Id = new LogicLong(selectAvatarMessage.AvatarIdHigherInt, selectAvatarMessage.AvatarIdLowerInt),
|
||||
|
||||
Name = "BreadDEV",
|
||||
AvatarCode = "a1",
|
||||
|
||||
TutorialFlags = 999999
|
||||
}
|
||||
LogicClientAvatar = _connection.LogicClientAvatar
|
||||
});
|
||||
}
|
||||
|
||||
[MessageHandler(10210)]
|
||||
public async Task OnTutorialProgressUpdate(TutorialProgressUpdateMessage tutorialProgressUpdateMessage)
|
||||
{
|
||||
_connection.LogicClientAvatar!.SetTutorialFlags(tutorialProgressUpdateMessage.TutorialFlags);
|
||||
|
||||
await _documentManager.SaveAsync();
|
||||
}
|
||||
|
||||
[MessageHandler(10504)]
|
||||
public async Task OnAskForFriendList(AskForFriendListMessage askForFriendListMessage)
|
||||
{
|
||||
await _connection.SendMessage(new FriendListMessage());
|
||||
}
|
||||
|
||||
[MessageHandler(10503)]
|
||||
public async Task OnAskForAddableFriends(AskForAddableFriendsMessage askForAddableFriendsMessage)
|
||||
{
|
||||
await _connection.SendMessage(new AddableFriendsMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.24.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
11
Supercell.GUT.Server/Util/TimeUtil.cs
Normal file
11
Supercell.GUT.Server/Util/TimeUtil.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Supercell.GUT.Server.Util;
|
||||
|
||||
public static class TimeUtil
|
||||
{
|
||||
private static readonly DateTime s_unixTime = new(1970, 1, 1);
|
||||
|
||||
public static int GetCurrentTimestamp()
|
||||
{
|
||||
return (int)DateTime.UtcNow.Subtract(s_unixTime).TotalSeconds;
|
||||
}
|
||||
}
|
|
@ -2,5 +2,9 @@
|
|||
"Gateway": {
|
||||
"Host": "0.0.0.0",
|
||||
"Port": 9339
|
||||
},
|
||||
"Database": {
|
||||
"MongoConnectionString": "mongodb://127.0.0.1:27017",
|
||||
"DatabaseName": "gut"
|
||||
}
|
||||
}
|
|
@ -36,4 +36,12 @@ public class LogicLong
|
|||
this.HigherInt = byteStream.ReadInt();
|
||||
this.LowerInt = byteStream.ReadInt();
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is LogicLong logicLong)
|
||||
return logicLong.HigherInt == this.HigherInt && logicLong.LowerInt == this.LowerInt;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue