mirror of
https://github.com/EggLinks/DanhengServer-OpenSource.git
synced 2026-01-02 12:16:03 +08:00
Implement basic login
This commit is contained in:
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
[*.cs]
|
||||
|
||||
# IDE0022: 使用方法的程序块主体
|
||||
csharp_style_expression_bodied_methods = false
|
||||
@@ -15,6 +15,7 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SQLitePCLRaw.core" Version="2.1.8" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.1.8" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.143" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel
|
||||
{
|
||||
[ResourceEntity("AvatarConfig.json", true)]
|
||||
internal class AvatarConfigExcel : ExcelResource
|
||||
public class AvatarConfigExcel : ExcelResource
|
||||
{
|
||||
public int AvatarID { get; set; } = 0;
|
||||
public HashName AvatarName { get; set; } = new();
|
||||
|
||||
public List<AvatarSkillTreeConfigExcel> DefaultSkillTree = [];
|
||||
public override int GetId()
|
||||
{
|
||||
return AvatarID;
|
||||
33
Common/Data/Excel/AvatarSkillTreeConfigExcel.cs
Normal file
33
Common/Data/Excel/AvatarSkillTreeConfigExcel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Data.Excel
|
||||
{
|
||||
[ResourceEntity("AvatarSkillTreeConfig.json")]
|
||||
public class AvatarSkillTreeConfigExcel : ExcelResource
|
||||
{
|
||||
|
||||
public int PointID { get; set; }
|
||||
public int Level { get; set; }
|
||||
public int AvatarID { get; set; }
|
||||
public bool DefaultUnlock { get; set; }
|
||||
public int MaxLevel { get; set; }
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return (PointID << 4) + Level;
|
||||
}
|
||||
|
||||
public override void AfterAllDone()
|
||||
{
|
||||
GameData.AvatarConfigData.TryGetValue(AvatarID, out var excel);
|
||||
if (excel != null && DefaultUnlock)
|
||||
{
|
||||
excel.DefaultSkillTree.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Common/Data/Excel/MapEntranceExcel.cs
Normal file
25
Common/Data/Excel/MapEntranceExcel.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel
|
||||
{
|
||||
[ResourceEntity("MapEntrance.json", true)]
|
||||
public class MapEntranceExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int PlaneID { get; set; }
|
||||
public int FloorID { get; set; }
|
||||
public int StartGroupID { get; set; }
|
||||
public int StartAnchorID { get; set; }
|
||||
|
||||
public List<int> FinishMainMissionList { get; set; } = [];
|
||||
public List<int> FinishSubMissionList { get; set; } = [];
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.MapEntranceData.Add(ID, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel
|
||||
{
|
||||
[ResourceEntity("StageConfig.json", false)]
|
||||
internal class StageConfigExcel : ExcelResource
|
||||
public class StageConfigExcel : ExcelResource
|
||||
{
|
||||
public int StageID { get; set; } = 0;
|
||||
public HashName StageName { get; set; } = new HashName();
|
||||
@@ -20,7 +20,7 @@ namespace EggLink.DanhengServer.Data.Excel
|
||||
}
|
||||
}
|
||||
|
||||
internal class StageMonsterList
|
||||
public class StageMonsterList
|
||||
{
|
||||
public int Monster0 { get; set; } = 0;
|
||||
public int Monster1 { get; set; } = 0;
|
||||
@@ -29,7 +29,7 @@ namespace EggLink.DanhengServer.Data.Excel
|
||||
public int Monster4 { get; set; } = 0;
|
||||
}
|
||||
|
||||
internal class HashName
|
||||
public class HashName
|
||||
{
|
||||
public long Hash { get; set; } = 0;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Data
|
||||
{
|
||||
internal abstract class ExcelResource
|
||||
public abstract class ExcelResource
|
||||
{
|
||||
public abstract int GetId();
|
||||
|
||||
@@ -17,5 +17,9 @@ namespace EggLink.DanhengServer.Data
|
||||
public virtual void Finalized()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void AfterAllDone()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,10 @@ using System.Collections.Generic;
|
||||
|
||||
namespace EggLink.DanhengServer.Data
|
||||
{
|
||||
internal static class GameData
|
||||
public static class GameData
|
||||
{
|
||||
public static Dictionary<int, AvatarConfigExcel> AvatarConfigData { get; private set; } = new Dictionary<int, AvatarConfigExcel>();
|
||||
public static Dictionary<int, StageConfigExcel> StageConfigData { get; private set; } = new Dictionary<int, StageConfigExcel>();
|
||||
public static Dictionary<int, AvatarConfigExcel> AvatarConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, StageConfigExcel> StageConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, MapEntranceExcel> MapEntranceData { get; private set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using EggLink.DanhengServer.Program;
|
||||
using EggLink.DanhengServer.Util;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace EggLink.DanhengServer.Data
|
||||
{
|
||||
internal class ResourceManager
|
||||
public class ResourceManager
|
||||
{
|
||||
public static Logger Logger { get; private set; } = new Logger("ResourceManager");
|
||||
public static void LoadGameData()
|
||||
@@ -21,12 +20,12 @@ namespace EggLink.DanhengServer.Data
|
||||
var classes = Assembly.GetExecutingAssembly().GetTypes(); // Get all classes in the assembly
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
var attribute = (ResourceEntity)Attribute.GetCustomAttribute(cls, typeof(ResourceEntity));
|
||||
var attribute = (ResourceEntity)Attribute.GetCustomAttribute(cls, typeof(ResourceEntity))!;
|
||||
|
||||
if (attribute != null)
|
||||
{
|
||||
var resource = (ExcelResource)Activator.CreateInstance(cls);
|
||||
var path = EntryPoint.GetConfig().Path.ResourcePath + "/ExcelOutput/" + attribute.FileName;
|
||||
var resource = (ExcelResource)Activator.CreateInstance(cls)!;
|
||||
var path = ConfigManager.Config.Path.ResourcePath + "/ExcelOutput/" + attribute.FileName;
|
||||
var file = new FileInfo(path);
|
||||
if (!file.Exists)
|
||||
{
|
||||
@@ -52,7 +51,7 @@ namespace EggLink.DanhengServer.Data
|
||||
foreach (var item in jArray)
|
||||
{
|
||||
var res = JsonConvert.DeserializeObject(item.ToString(), cls);
|
||||
((ExcelResource)res).Loaded();
|
||||
((ExcelResource?)res)?.Loaded();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -71,9 +70,9 @@ namespace EggLink.DanhengServer.Data
|
||||
var nestedObject = JsonConvert.DeserializeObject<JObject>(obj.ToString());
|
||||
|
||||
// Process only if it's a top-level dictionary, not nested
|
||||
if (nestedObject.Count > 0 && nestedObject.First.First.Type != JTokenType.Object)
|
||||
if (nestedObject?.Count > 0 && nestedObject?.First?.First?.Type != JTokenType.Object)
|
||||
{
|
||||
((ExcelResource)instance).Loaded();
|
||||
((ExcelResource?)instance)?.Loaded();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -84,9 +83,21 @@ namespace EggLink.DanhengServer.Data
|
||||
}
|
||||
}
|
||||
}
|
||||
resource.Finalized();
|
||||
|
||||
Logger.Info($"Loaded {count} {cls.Name}s.");
|
||||
}
|
||||
}
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
var attribute = (ResourceEntity)Attribute.GetCustomAttribute(cls, typeof(ResourceEntity))!;
|
||||
|
||||
if (attribute != null)
|
||||
{
|
||||
var resource = (ExcelResource)Activator.CreateInstance(cls)!;
|
||||
resource.AfterAllDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +1,53 @@
|
||||
using EggLink.DanhengServer.Util;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using SqlSugar;
|
||||
|
||||
namespace EggLink.DanhengServer.Database.Account
|
||||
{
|
||||
[DatabaseEntity("account")]
|
||||
public class AccountData(string username, long uid, string comboToken = "", string dispatchToken = "", string permissions = "") : BaseDatabaseData
|
||||
[SugarTable("Account")]
|
||||
public class AccountData() : BaseDatabaseData
|
||||
{
|
||||
public string Username { get; set; } = username;
|
||||
public long Uid { get; set; } = uid;
|
||||
public string ComboToken { get; set; } = comboToken;
|
||||
public string DispatchToken { get; set; } = dispatchToken;
|
||||
public string Permissions { get; set; } = permissions; // type: permission1,permission2,permission3...
|
||||
public string? Username { get; set; }
|
||||
|
||||
public static BaseDatabaseData? GetAccountByUserName(string username)
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public string? ComboToken { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public string? DispatchToken { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public string? Permissions { get; set; } // type: permission1,permission2,permission3...
|
||||
|
||||
public static AccountData? GetAccountByUserName(string username)
|
||||
{
|
||||
var connection = DatabaseHelper.Instance.connection;
|
||||
var command = new SqliteCommand("SELECT * FROM account", connection);
|
||||
var reader = command.ExecuteReader();
|
||||
AccountData? result = null;
|
||||
while (reader.Read())
|
||||
DatabaseHelper.Instance?.GetAllInstance<AccountData>()?.ForEach((account) =>
|
||||
{
|
||||
if (reader.GetString(0) == username)
|
||||
if (account.Username == username)
|
||||
{
|
||||
result = new(reader.GetString(0), reader.GetInt64(1), reader.GetString(2), reader.GetString(3), reader.GetString(4));
|
||||
break;
|
||||
result = account;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BaseDatabaseData? GetAccountByUid(long uid)
|
||||
public static AccountData? GetAccountByUid(long uid)
|
||||
{
|
||||
var connection = DatabaseHelper.Instance.connection;
|
||||
var command = new SqliteCommand("SELECT * FROM account", connection);
|
||||
var reader = command.ExecuteReader();
|
||||
AccountData? result = null;
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.GetInt64(1) == uid)
|
||||
{
|
||||
result = new(reader.GetString(0), reader.GetInt64(1), reader.GetString(2), reader.GetString(3), reader.GetString(4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
AccountData? result = DatabaseHelper.Instance?.GetInstance<AccountData>(uid);
|
||||
return result;
|
||||
}
|
||||
|
||||
public string GenerateDispatchToken()
|
||||
{
|
||||
DispatchToken = Crypto.CreateSessionKey(Uid.ToString());
|
||||
ModifyDatabase(Uid, "dispatchToken", DispatchToken);
|
||||
DatabaseHelper.Instance?.UpdateInstance(this);
|
||||
return DispatchToken;
|
||||
}
|
||||
|
||||
public string GenerateComboToken()
|
||||
{
|
||||
ComboToken = Crypto.CreateSessionKey(Uid.ToString());
|
||||
ModifyDatabase(Uid, "comboToken", ComboToken);
|
||||
DatabaseHelper.Instance?.UpdateInstance(this);
|
||||
return ComboToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace EggLink.DanhengServer.Database.Account
|
||||
long newUid = uid;
|
||||
if (uid == 0)
|
||||
{
|
||||
newUid = 10000; // start from 10000
|
||||
newUid = 10001; // start from 10001
|
||||
while (AccountData.GetAccountByUid(newUid) != null)
|
||||
{
|
||||
newUid++;
|
||||
@@ -25,8 +25,13 @@ namespace EggLink.DanhengServer.Database.Account
|
||||
}
|
||||
var per = ConfigManager.Config.ServerOption.DefaultPermissions;
|
||||
var perStr = string.Join(",", per);
|
||||
var account = new AccountData(username,newUid, permissions: perStr);
|
||||
account.SaveToDatabase();
|
||||
var account = new AccountData()
|
||||
{
|
||||
Uid = newUid,
|
||||
Username = username,
|
||||
Permissions = perStr
|
||||
};
|
||||
DatabaseHelper.Instance?.SaveInstance(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
97
Common/Database/Avatar/AvatarData.cs
Normal file
97
Common/Database/Avatar/AvatarData.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace EggLink.DanhengServer.Database.Avatar
|
||||
{
|
||||
[SugarTable("Avatar")]
|
||||
public class AvatarData : BaseDatabaseData
|
||||
{
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public List<AvatarInfo>? Avatars { get; set; }
|
||||
|
||||
public List<int> AssistAvatars { get; set; } = [];
|
||||
public List<int> DisplayAvatars { get; set; } = [];
|
||||
}
|
||||
|
||||
public class AvatarInfo
|
||||
{
|
||||
public int AvatarId { get; set; }
|
||||
public int Level { get; set; }
|
||||
public int Exp { get; set; }
|
||||
public int Promotion { get; set; }
|
||||
public int Rewards { get; set; }
|
||||
public long Timestamp { get; set; }
|
||||
public int CurrentHp { get; set; }
|
||||
public int CurrentSp { get; set; }
|
||||
public int ExtraLineupHp { get; set; }
|
||||
public int ExtraLineupSp { get; set; }
|
||||
public int Rank { get; set; }
|
||||
public Dictionary<int, int> SkillTree { get; set; } = [];
|
||||
public int EquipId { get; set; } = 0;
|
||||
public Dictionary<int, int> Relic { get; set; } = [];
|
||||
|
||||
public AvatarConfigExcel Excel;
|
||||
|
||||
public AvatarInfo(AvatarConfigExcel excel)
|
||||
{
|
||||
Excel = excel;
|
||||
SkillTree = [];
|
||||
excel.DefaultSkillTree.ForEach(skill =>
|
||||
{
|
||||
SkillTree.Add(skill.PointID, skill.Level);
|
||||
});
|
||||
}
|
||||
|
||||
public bool HasTakenReward(int promotion)
|
||||
{
|
||||
return (Rewards & (1 << promotion)) != 0;
|
||||
}
|
||||
|
||||
public Proto.Avatar ToProto()
|
||||
{
|
||||
var proto = new Proto.Avatar()
|
||||
{
|
||||
BaseAvatarId = (uint)AvatarId,
|
||||
Level = (uint)Level,
|
||||
Exp = (uint)Exp,
|
||||
Promotion = (uint)Promotion,
|
||||
Rank = (uint)Rank,
|
||||
FirstMetTimestamp = (ulong)Timestamp,
|
||||
};
|
||||
|
||||
foreach (var item in Relic)
|
||||
{
|
||||
proto.EquipRelicList.Add(new EquipRelic()
|
||||
{
|
||||
RelicUniqueId = (uint)item.Value,
|
||||
Slot = (uint)item.Key
|
||||
});
|
||||
}
|
||||
|
||||
if (EquipId != 0)
|
||||
{
|
||||
proto.EquipmentUniqueId = (uint)EquipId;
|
||||
}
|
||||
|
||||
foreach (var skill in SkillTree)
|
||||
{
|
||||
proto.SkilltreeList.Add(new AvatarSkillTree()
|
||||
{
|
||||
PointId = (uint)skill.Key,
|
||||
Level = (uint)skill.Value
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < Promotion; i++)
|
||||
{
|
||||
if (HasTakenReward(i))
|
||||
{
|
||||
proto.TakenRewards.Add((uint)i);
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +1,11 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using SqlSugar;
|
||||
|
||||
namespace EggLink.DanhengServer.Database
|
||||
{
|
||||
public abstract class BaseDatabaseData
|
||||
{
|
||||
public void SaveToDatabase()
|
||||
{
|
||||
var connection = DatabaseHelper.Instance.connection;
|
||||
var attributes = GetType().GetCustomAttributes(true);
|
||||
string tableName = "";
|
||||
foreach ( var attribute in attributes )
|
||||
{
|
||||
if (attribute is DatabaseEntity)
|
||||
{
|
||||
tableName = (attribute as DatabaseEntity).TableName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var command = new SqliteCommand($"INSERT INTO {tableName} (", connection);
|
||||
var properties = GetType().GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
command.CommandText += $"{property.Name}, ";
|
||||
}
|
||||
command.CommandText = command.CommandText[..^2];
|
||||
command.CommandText += ") VALUES (";
|
||||
foreach (var property in properties)
|
||||
{
|
||||
command.CommandText += $"\"{property.GetValue(this)}\", ";
|
||||
}
|
||||
command.CommandText = command.CommandText[..^2];
|
||||
command.CommandText += ")";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public void ModifyDatabase(long uid, string property, string value)
|
||||
{
|
||||
var connection = DatabaseHelper.Instance.connection;
|
||||
var attributes = GetType().GetCustomAttributes(true);
|
||||
string tableName = "";
|
||||
foreach ( var attribute in attributes )
|
||||
{
|
||||
if (attribute is DatabaseEntity)
|
||||
{
|
||||
tableName = (attribute as DatabaseEntity).TableName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var command = new SqliteCommand($"UPDATE {tableName} SET \"{property}\" = \"{value}\" WHERE UID = {uid};", connection);
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public void DeleteFromDatabase()
|
||||
{
|
||||
var connection = DatabaseHelper.Instance.connection;
|
||||
var attributes = GetType().GetCustomAttributes(true);
|
||||
string tableName = "";
|
||||
foreach ( var attribute in attributes )
|
||||
{
|
||||
if (attribute is DatabaseEntity)
|
||||
{
|
||||
tableName = (attribute as DatabaseEntity).TableName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var command = new SqliteCommand($"DELETE FROM {tableName} WHERE ", connection);
|
||||
var properties = GetType().GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
command.CommandText += $"{property.Name} = {property.GetValue(this)} AND ";
|
||||
}
|
||||
command.CommandText = command.CommandText[..^5];
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public long Uid { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace EggLink.DanhengServer.Database
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class DatabaseEntity(string tableName) : Attribute
|
||||
{
|
||||
public string TableName { get; set; } = tableName;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using EggLink.DanhengServer.Configuration;
|
||||
using EggLink.DanhengServer.Database.Account;
|
||||
using EggLink.DanhengServer.Util;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using SqlSugar;
|
||||
using System.Reflection;
|
||||
|
||||
namespace EggLink.DanhengServer.Database
|
||||
@@ -9,8 +11,8 @@ namespace EggLink.DanhengServer.Database
|
||||
{
|
||||
public Logger logger = new("Database");
|
||||
public ConfigContainer config = ConfigManager.Config;
|
||||
public SqliteConnection connection;
|
||||
public static DatabaseHelper Instance;
|
||||
public static SqlSugarScope? sqlSugarScope;
|
||||
public static DatabaseHelper? Instance;
|
||||
|
||||
public DatabaseHelper()
|
||||
{
|
||||
@@ -19,7 +21,12 @@ namespace EggLink.DanhengServer.Database
|
||||
{
|
||||
f.Directory.Create();
|
||||
}
|
||||
connection = new SqliteConnection($"Data Source={f.FullName};");
|
||||
sqlSugarScope = new(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = $"Data Source={f.FullName};",
|
||||
DbType = DbType.Sqlite,
|
||||
IsAutoCloseConnection = true,
|
||||
});
|
||||
Instance = this;
|
||||
}
|
||||
public void Initialize()
|
||||
@@ -36,70 +43,65 @@ namespace EggLink.DanhengServer.Database
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeSqlite()
|
||||
public static void InitializeSqlite()
|
||||
{
|
||||
SQLitePCL.Batteries.Init();
|
||||
connection.Open();
|
||||
var classes = Assembly.GetExecutingAssembly().GetTypes();
|
||||
foreach (var cls in classes) {
|
||||
var attribute = (DatabaseEntity)Attribute.GetCustomAttribute(cls, typeof(DatabaseEntity));
|
||||
if (attribute != null)
|
||||
{
|
||||
var tableName = attribute.TableName;
|
||||
var createTable = $"CREATE TABLE IF NOT EXISTS {tableName} (";
|
||||
var properties = cls.GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
createTable += $"{property.Name} {GetSqliteType(property.PropertyType)}, ";
|
||||
}
|
||||
createTable = createTable.Substring(0, createTable.Length - 2);
|
||||
createTable += ")";
|
||||
var command = new SqliteCommand(createTable, connection);
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
var baseType = typeof(BaseDatabaseData);
|
||||
var assembly = typeof(BaseDatabaseData).Assembly;
|
||||
var types = assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
|
||||
foreach (var type in types)
|
||||
{
|
||||
typeof(DatabaseHelper).GetMethod("InitializeSqliteTable")?.MakeGenericMethod(type).Invoke(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSqliteType(Type propertyType)
|
||||
public static void InitializeSqliteTable<T>() where T : class, new()
|
||||
{
|
||||
if (propertyType == typeof(int))
|
||||
try
|
||||
{
|
||||
return "INTEGER";
|
||||
}
|
||||
else if (propertyType == typeof(string))
|
||||
sqlSugarScope?.Queryable<T>().ToList();
|
||||
} catch
|
||||
{
|
||||
return "TEXT";
|
||||
}
|
||||
else if (propertyType == typeof(bool))
|
||||
{
|
||||
return "INTEGER";
|
||||
}
|
||||
else if (propertyType == typeof(float))
|
||||
{
|
||||
return "REAL";
|
||||
}
|
||||
else if (propertyType == typeof(double))
|
||||
{
|
||||
return "REAL";
|
||||
}
|
||||
else if (propertyType == typeof(long))
|
||||
{
|
||||
return "INTEGER";
|
||||
}
|
||||
else if (propertyType == typeof(byte[]))
|
||||
{
|
||||
return "BLOB";
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"Unsupported type {propertyType}");
|
||||
return "TEXT";
|
||||
sqlSugarScope?.CodeFirst.InitTables<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
public T? GetInstance<T>(long uid) where T : class, new()
|
||||
{
|
||||
connection.Close();
|
||||
try
|
||||
{
|
||||
return sqlSugarScope?.Queryable<T>().Where(it => (it as BaseDatabaseData).Uid == uid).First();
|
||||
} catch
|
||||
{
|
||||
logger.Error("Unsupported type");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<T>? GetAllInstance<T>() where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
return sqlSugarScope?.Queryable<T>().ToList();
|
||||
} catch
|
||||
{
|
||||
logger.Error("Unsupported type");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveInstance<T>(T instance) where T : class, new()
|
||||
{
|
||||
sqlSugarScope?.Insertable(instance).ExecuteCommand();
|
||||
}
|
||||
|
||||
public void UpdateInstance<T>(T instance) where T : class, new()
|
||||
{
|
||||
sqlSugarScope?.Updateable(instance).ExecuteCommand();
|
||||
}
|
||||
|
||||
public void DeleteInstance<T>(T instance) where T : class, new()
|
||||
{
|
||||
sqlSugarScope?.Deleteable(instance).ExecuteCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
95
Common/Database/Inventory/InventoryData.cs
Normal file
95
Common/Database/Inventory/InventoryData.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace EggLink.DanhengServer.Database.Inventory
|
||||
{
|
||||
public class InventoryData : BaseDatabaseData
|
||||
{
|
||||
[SugarColumn(IsJson = true)]
|
||||
public List<ItemData> MaterialItems { get; set; } = [];
|
||||
[SugarColumn(IsJson = true)]
|
||||
public List<ItemData> EquipmentItems { get; set; } = [];
|
||||
[SugarColumn(IsJson = true)]
|
||||
public List<ItemData> RelicItems { get; set; } = [];
|
||||
}
|
||||
|
||||
public class ItemData
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public int UniqueId { get; set; }
|
||||
public int ItemId { get; set; }
|
||||
public int Count { get; set; }
|
||||
public int Level { get; set; }
|
||||
public int Exp { get; set; }
|
||||
public int TotalExp { get; set; }
|
||||
public int Promotion { get; set; }
|
||||
public int Rank { get; set; } // Superimpose
|
||||
public bool Locked { get; set; }
|
||||
public bool Discarded { get; set; }
|
||||
|
||||
public int MainAffix { get; set; }
|
||||
public List<ItemSubAffix> SubAffixes { get; set; } = [];
|
||||
|
||||
public int EquipAvatar { get; set; }
|
||||
|
||||
public Material ToMaterialProto()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Tid = (uint)ItemId,
|
||||
Num = (uint)Count,
|
||||
};
|
||||
}
|
||||
|
||||
public Relic ToRelicProto()
|
||||
{
|
||||
Relic relic = new()
|
||||
{
|
||||
Tid = (uint)ItemId,
|
||||
UniqueId = (uint)UniqueId,
|
||||
Level = (uint)Level,
|
||||
IsProtected = Locked,
|
||||
IsDiscarded = Discarded,
|
||||
BaseAvatarId = (uint)EquipAvatar,
|
||||
MainAffixId = (uint)MainAffix,
|
||||
};
|
||||
if (SubAffixes.Count >= 1)
|
||||
{
|
||||
foreach (var subAffix in SubAffixes)
|
||||
{
|
||||
relic.SubAffixList.Add(subAffix.ToProto());
|
||||
}
|
||||
}
|
||||
return relic;
|
||||
}
|
||||
public Equipment ToEquipmentProto()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Tid = (uint)ItemId,
|
||||
UniqueId = (uint)UniqueId,
|
||||
Level = (uint)Level,
|
||||
Exp = (uint)Exp,
|
||||
IsProtected = Locked,
|
||||
Promotion = (uint)Promotion,
|
||||
Rank = (uint)Rank,
|
||||
BaseAvatarId = (uint)EquipAvatar
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemSubAffix
|
||||
{
|
||||
public int Id { get; set; } // Affix id
|
||||
|
||||
public int Count { get; set; }
|
||||
public int Step { get; set; }
|
||||
|
||||
public RelicAffix ToProto() => new()
|
||||
{
|
||||
AffixId = (uint)Id,
|
||||
Cnt = (uint)Count,
|
||||
Step = (uint)Step
|
||||
};
|
||||
}
|
||||
}
|
||||
28
Common/Database/Lineup/LineupData.cs
Normal file
28
Common/Database/Lineup/LineupData.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Database.Lineup
|
||||
{
|
||||
[SugarTable("Lineup")]
|
||||
public class LineupData : BaseDatabaseData
|
||||
{
|
||||
public int CurLineup { get; set; } // index of current lineup
|
||||
public string? Lineups { get; set; } // 9 * 4
|
||||
}
|
||||
|
||||
public class LineupInfo
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public int LineupType { get; set; }
|
||||
public List<int>? BaseAvatars { get; set; }
|
||||
}
|
||||
|
||||
public class LineupInfoJson
|
||||
{
|
||||
public Dictionary<int, LineupInfo>? Lineups { get; set; } = []; // 9 * 4
|
||||
}
|
||||
}
|
||||
48
Common/Database/Player/PlayerData.cs
Normal file
48
Common/Database/Player/PlayerData.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using EggLink.DanhengServer.Enums;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Util;
|
||||
using SqlSugar;
|
||||
|
||||
namespace EggLink.DanhengServer.Database.Player
|
||||
{
|
||||
[SugarTable("Player")]
|
||||
public class PlayerData : BaseDatabaseData
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Signature { get; set; }
|
||||
public int Birthday { get; set; }
|
||||
public int CurBasicType { get; set; }
|
||||
public int HeadIcon { get; set; }
|
||||
public int PhoneTheme { get; set; }
|
||||
public int ChatBubble { get; set; }
|
||||
public int CurrentBgm { get; set; }
|
||||
public Gender? CurrentGender { get; set; }
|
||||
public int Level { get; set; }
|
||||
public int Exp { get; set; }
|
||||
public int WorldLevel { get; set; }
|
||||
public int Scoin { get; set; } // Credits
|
||||
public int Hcoin { get; set; } // Jade
|
||||
public int Mcoin { get; set; } // Crystals
|
||||
public int TalentPoints { get; set; } // Rogue talent points
|
||||
|
||||
public int Stamina { get; set; }
|
||||
public double StaminaReserve { get; set; }
|
||||
public long NextStaminaRecover { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public Position? Pos { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public Position? Rot { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public int PlaneId { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public int FloorId { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public int EntryId { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public long LastActiveTime { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
9
Common/Database/Player/PlayerUnlockData.cs
Normal file
9
Common/Database/Player/PlayerUnlockData.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace EggLink.DanhengServer.Database.Player
|
||||
{
|
||||
public class PlayerUnlockData : BaseDatabaseData
|
||||
{
|
||||
public List<int> HeadIcons { get; set; } = [];
|
||||
public List<int> ChatBubbles { get; set; } = [];
|
||||
public List<int> PhoneThemes { get; set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,11 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Player
|
||||
namespace EggLink.DanhengServer.Enums
|
||||
{
|
||||
public class Player
|
||||
public enum PlayerGender
|
||||
{
|
||||
public async Task OnLogoutAsync()
|
||||
{
|
||||
|
||||
}
|
||||
PLAYER_MALE = 0,
|
||||
PLAYER_FEMALE = 1,
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace EggLink.DanhengServer.Enums
|
||||
namespace EggLink.DanhengServer.Common.Enums
|
||||
{
|
||||
public enum SessionState
|
||||
{
|
||||
20
Common/Util/GameConstants.cs
Normal file
20
Common/Util/GameConstants.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Util
|
||||
{
|
||||
public static class GameConstants
|
||||
{
|
||||
public const int MATERIAL_HCOIN_ID = 1; // Material id for jades. DO NOT CHANGE
|
||||
public const int MATERIAL_COIN_ID = 2; // Material id for credits. DO NOT CHANGE
|
||||
public const int TRAILBLAZER_EXP_ID = 22;
|
||||
public const int RELIC_REMAINS_ID = 235;
|
||||
|
||||
public const int INVENTORY_MAX_EQUIPMENT = 1500;
|
||||
public const int INVENTORY_MAX_RELIC = 1500;
|
||||
public const int INVENTORY_MAX_MATERIAL = 2000;
|
||||
}
|
||||
}
|
||||
@@ -107,10 +107,9 @@ namespace EggLink.DanhengServer.Util
|
||||
}
|
||||
}
|
||||
|
||||
public static Logger GetByClassName()
|
||||
{
|
||||
return new Logger(new StackTrace().GetFrame(1).GetMethod().ReflectedType.Name);
|
||||
}
|
||||
#pragma warning disable CS8602
|
||||
public static Logger GetByClassName() => new(new StackTrace().GetFrame(1).GetMethod().ReflectedType.Name);
|
||||
#pragma warning restore CS8602
|
||||
}
|
||||
|
||||
public enum LoggerLevel
|
||||
|
||||
121
Common/Util/Position.cs
Normal file
121
Common/Util/Position.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Util
|
||||
{
|
||||
public class Position
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public int Z { get; set; }
|
||||
|
||||
public Position(int x, int y, int z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public Position(Vector vector)
|
||||
{
|
||||
X = vector.X;
|
||||
Y = vector.Y;
|
||||
Z = vector.Z;
|
||||
}
|
||||
|
||||
public Position()
|
||||
{
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Z = 0;
|
||||
}
|
||||
|
||||
public Position(Position position)
|
||||
{
|
||||
X = position.X;
|
||||
Y = position.Y;
|
||||
Z = position.Z;
|
||||
}
|
||||
|
||||
public void Set(int x, int y, int z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public void Set(Position position)
|
||||
{
|
||||
X = position.X;
|
||||
Y = position.Y;
|
||||
Z = position.Z;
|
||||
}
|
||||
|
||||
public void Set(Vector vector)
|
||||
{
|
||||
X = vector.X;
|
||||
Y = vector.Y;
|
||||
Z = vector.Z;
|
||||
}
|
||||
|
||||
public void Add(int x, int y, int z)
|
||||
{
|
||||
X += x;
|
||||
Y += y;
|
||||
Z += z;
|
||||
}
|
||||
|
||||
public void Add(Position position)
|
||||
{
|
||||
X += position.X;
|
||||
Y += position.Y;
|
||||
Z += position.Z;
|
||||
}
|
||||
|
||||
public void Sub(int x, int y, int z)
|
||||
{
|
||||
X -= x;
|
||||
Y -= y;
|
||||
Z -= z;
|
||||
}
|
||||
|
||||
public void Sub(Position position)
|
||||
{
|
||||
X -= position.X;
|
||||
Y -= position.Y;
|
||||
Z -= position.Z;
|
||||
}
|
||||
|
||||
public void Mul(int x, int y, int z)
|
||||
{
|
||||
X *= x;
|
||||
Y *= y;
|
||||
Z *= z;
|
||||
}
|
||||
|
||||
public void Mul(Position position)
|
||||
{
|
||||
X *= position.X;
|
||||
Y *= position.Y;
|
||||
Z *= position.Z;
|
||||
}
|
||||
|
||||
public void Div(int x, int y, int z)
|
||||
{
|
||||
X /= x;
|
||||
Y /= y;
|
||||
Z /= z;
|
||||
}
|
||||
|
||||
public void Div(Position position)
|
||||
{
|
||||
X /= position.X;
|
||||
Y /= position.Y;
|
||||
Z /= position.Z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0C822679-4BCC-497A-AF15-F441EC750CCE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
||||
56
GameServer/Game/Avatar/AvatarManager.cs
Normal file
56
GameServer/Game/Avatar/AvatarManager.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Avatar;
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Avatar
|
||||
{
|
||||
public class AvatarManager : BasePlayerManager
|
||||
{
|
||||
public AvatarData AvatarData { get; private set; }
|
||||
|
||||
public AvatarManager(PlayerInstance player) : base(player)
|
||||
{
|
||||
var avatars = DatabaseHelper.Instance?.GetInstance<AvatarData>(player.Uid);
|
||||
if (avatars == null)
|
||||
{
|
||||
AvatarData = new()
|
||||
{
|
||||
Uid = player.Uid,
|
||||
Avatars = [],
|
||||
};
|
||||
DatabaseHelper.Instance?.SaveInstance(AvatarData);
|
||||
}
|
||||
else
|
||||
{
|
||||
AvatarData = avatars;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAvatar(int avatarId)
|
||||
{
|
||||
GameData.AvatarConfigData.TryGetValue(avatarId, out AvatarConfigExcel? avatarExcel);
|
||||
if (avatarExcel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var avatar = new AvatarInfo(avatarExcel)
|
||||
{
|
||||
AvatarId = avatarId,
|
||||
Level = 1,
|
||||
Timestamp = DateTime.Now.Ticks / TimeSpan.TicksPerSecond,
|
||||
CurrentHp = 10000,
|
||||
CurrentSp = 0
|
||||
};
|
||||
|
||||
if (AvatarData.Avatars == null)
|
||||
{
|
||||
AvatarData.Avatars = [];
|
||||
}
|
||||
|
||||
AvatarData.Avatars.Add(avatar);
|
||||
DatabaseHelper.Instance?.UpdateInstance(AvatarData);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
GameServer/Game/BasePlayerManager.cs
Normal file
14
GameServer/Game/BasePlayerManager.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Game
|
||||
{
|
||||
public class BasePlayerManager(PlayerInstance player)
|
||||
{
|
||||
public PlayerInstance Player { get; private set; } = player;
|
||||
}
|
||||
}
|
||||
26
GameServer/Game/Inventory/InventoryManager.cs
Normal file
26
GameServer/Game/Inventory/InventoryManager.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Inventory;
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Inventory
|
||||
{
|
||||
public class InventoryManager : BasePlayerManager
|
||||
{
|
||||
public InventoryData Data;
|
||||
public InventoryManager(PlayerInstance player) : base(player)
|
||||
{
|
||||
var inventory = DatabaseHelper.Instance?.GetInstance<InventoryData>(player.Uid);
|
||||
if (inventory == null)
|
||||
{
|
||||
DatabaseHelper.Instance?.SaveInstance(new InventoryData()
|
||||
{
|
||||
Uid = player.Uid,
|
||||
});
|
||||
inventory = DatabaseHelper.Instance?.GetInstance<InventoryData>(player.Uid);
|
||||
}
|
||||
Data = inventory!;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
95
GameServer/Game/Lineup/LineupManager.cs
Normal file
95
GameServer/Game/Lineup/LineupManager.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Lineup;
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Lineup
|
||||
{
|
||||
public class LineupManager : BasePlayerManager
|
||||
{
|
||||
public LineupData LineupData { get; private set; }
|
||||
public LineupInfoJson LineupInfoJson { get; private set; }
|
||||
|
||||
public LineupManager(PlayerInstance player) : base(player)
|
||||
{
|
||||
var lineup = DatabaseHelper.Instance?.GetInstance<LineupData>(player.Uid);
|
||||
if (lineup == null)
|
||||
{
|
||||
LineupData = new()
|
||||
{
|
||||
Uid = player.Uid,
|
||||
CurLineup = 0,
|
||||
Lineups = "{}",
|
||||
};
|
||||
DatabaseHelper.Instance?.SaveInstance(LineupData);
|
||||
}
|
||||
else
|
||||
{
|
||||
LineupData = lineup;
|
||||
}
|
||||
LineupInfoJson = JsonConvert.DeserializeObject<LineupInfoJson>(LineupData.Lineups ?? "{}") ?? new();
|
||||
}
|
||||
|
||||
public LineupInfo? GetLineup(int lineupIndex)
|
||||
{
|
||||
if (LineupData.Lineups == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (lineupIndex < 0 || lineupIndex >= LineupInfoJson.Lineups?.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return LineupInfoJson.Lineups?[lineupIndex];
|
||||
}
|
||||
|
||||
public LineupInfo? GetCurLineup()
|
||||
{
|
||||
return GetLineup(LineupData.CurLineup);
|
||||
}
|
||||
|
||||
public void SetCurLineup(int lineupIndex)
|
||||
{
|
||||
if (lineupIndex < 0 || lineupIndex >= LineupInfoJson.Lineups?.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LineupData.CurLineup = lineupIndex;
|
||||
DatabaseHelper.Instance?.UpdateInstance(LineupData);
|
||||
}
|
||||
|
||||
public void AddAvatar(int lineupIndex, int avatarId)
|
||||
{
|
||||
if (lineupIndex < 0 || LineupData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (LineupData.Lineups == null)
|
||||
{
|
||||
LineupData.Lineups = "";
|
||||
}
|
||||
LineupInfo? lineup = null;
|
||||
LineupInfoJson.Lineups?.TryGetValue(lineupIndex, out lineup);
|
||||
if (lineup == null)
|
||||
{
|
||||
lineup = new()
|
||||
{
|
||||
Name = "Lineup " + lineupIndex,
|
||||
LineupType = 0,
|
||||
BaseAvatars = [avatarId],
|
||||
};
|
||||
LineupInfoJson.Lineups?.Add(lineupIndex, lineup);
|
||||
} else
|
||||
{
|
||||
lineup.BaseAvatars?.Add(avatarId);
|
||||
}
|
||||
LineupData.Lineups = JsonConvert.SerializeObject(LineupInfoJson);
|
||||
DatabaseHelper.Instance?.UpdateInstance(LineupData!);
|
||||
}
|
||||
|
||||
public void AddAvatarToCurTeam(int avatarId)
|
||||
{
|
||||
AddAvatar(LineupData.CurLineup, avatarId);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
GameServer/Game/Player/PlayerInstance.cs
Normal file
138
GameServer/Game/Player/PlayerInstance.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Player;
|
||||
using EggLink.DanhengServer.Enums;
|
||||
using EggLink.DanhengServer.Game.Avatar;
|
||||
using EggLink.DanhengServer.Game.Inventory;
|
||||
using EggLink.DanhengServer.Game.Lineup;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Server;
|
||||
using EggLink.DanhengServer.Server.Packet;
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Player
|
||||
{
|
||||
public class PlayerInstance(PlayerData data)
|
||||
{
|
||||
public PlayerData Data { get; set; } = data;
|
||||
public ushort Uid { get; set; }
|
||||
public Connection? Connection { get; set; }
|
||||
public bool Initialized { get; set; } = false;
|
||||
|
||||
#region Managers
|
||||
|
||||
public AvatarManager AvatarManager { get; private set; }
|
||||
public LineupManager LineupManager { get; private set; }
|
||||
public InventoryManager InventoryManager { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Datas
|
||||
|
||||
public PlayerUnlockData PlayerUnlockData { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public PlayerInstance() : this(new PlayerData())
|
||||
{
|
||||
// new player
|
||||
Data.Name = "无名客"; // Trailblazer in EN TODO: Add localization
|
||||
Data.Signature = "";
|
||||
Data.Birthday = 0;
|
||||
Data.CurBasicType = 8001;
|
||||
Data.HeadIcon = 208001;
|
||||
Data.PhoneTheme = 221000;
|
||||
Data.ChatBubble = 220000;
|
||||
Data.CurrentBgm = 210000;
|
||||
Data.CurrentGender = Gender.Man;
|
||||
Data.Stamina = 240;
|
||||
Data.StaminaReserve = 0;
|
||||
Data.NextStaminaRecover = DateTime.Now.Millisecond;
|
||||
Data.Level = 1;
|
||||
Data.Exp = 0;
|
||||
Data.WorldLevel = 0;
|
||||
Data.Scoin = 0;
|
||||
Data.Hcoin = 0;
|
||||
Data.Mcoin = 0;
|
||||
Data.TalentPoints = 0;
|
||||
|
||||
InitialPlayerManager();
|
||||
|
||||
AddAvatar(1005);
|
||||
LineupManager.SetCurLineup(0);
|
||||
LineupManager.AddAvatarToCurTeam(1005);
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
private void InitialPlayerManager()
|
||||
{
|
||||
Uid = (ushort)Data.Uid;
|
||||
AvatarManager = new(this);
|
||||
LineupManager = new(this);
|
||||
InventoryManager = new(this);
|
||||
|
||||
var unlock = DatabaseHelper.Instance?.GetInstance<PlayerUnlockData>(Uid);
|
||||
if (unlock == null)
|
||||
{
|
||||
DatabaseHelper.Instance?.SaveInstance(new PlayerUnlockData()
|
||||
{
|
||||
Uid = Uid,
|
||||
});
|
||||
unlock = DatabaseHelper.Instance?.GetInstance<PlayerUnlockData>(Uid);
|
||||
}
|
||||
PlayerUnlockData = unlock!;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Network
|
||||
public void OnLogin()
|
||||
{
|
||||
if (!Initialized)
|
||||
{
|
||||
InitialPlayerManager();
|
||||
}
|
||||
|
||||
SendPacket(new PacketStaminaInfoScNotify(this));
|
||||
|
||||
}
|
||||
|
||||
public async Task OnLogoutAsync()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SendPacket(BasePacket packet)
|
||||
{
|
||||
Connection?.SendPacket(packet);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extra
|
||||
|
||||
public void AddAvatar(int avatarId)
|
||||
{
|
||||
AvatarManager.AddAvatar(avatarId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Proto
|
||||
|
||||
public PlayerBasicInfo ToProto()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Nickname = Data.Name,
|
||||
Level = (uint)Data.Level,
|
||||
Exp = (uint)Data.Exp,
|
||||
WorldLevel = (uint)Data.WorldLevel,
|
||||
Scoin = (uint)Data.Scoin,
|
||||
Hcoin = (uint)Data.Hcoin,
|
||||
Mcoin = (uint)Data.Mcoin,
|
||||
Stamina = (uint)Data.Stamina,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
12
GameServer/Game/Scene/SceneInstance.cs
Normal file
12
GameServer/Game/Scene/SceneInstance.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Game.Scene
|
||||
{
|
||||
public class SceneInstance
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Server\Packet\Recv\Rogue\" />
|
||||
<Folder Include="Server\Packet\Recv\Scene\" />
|
||||
<Folder Include="Server\Packet\Recv\Achievement\" />
|
||||
<Folder Include="Server\Packet\Recv\ChessRogue\" />
|
||||
<Folder Include="Server\Packet\Recv\Tutorial\" />
|
||||
<Folder Include="Server\Packet\Recv\Mission\" />
|
||||
<Folder Include="Server\Packet\Recv\Quest\" />
|
||||
<Folder Include="Server\Packet\Recv\Mail\" />
|
||||
<Folder Include="Server\Packet\Recv\Friend\" />
|
||||
@@ -31,18 +29,16 @@
|
||||
<Folder Include="Server\Packet\Send\ChessRogue\" />
|
||||
<Folder Include="Server\Packet\Send\Friend\" />
|
||||
<Folder Include="Server\Packet\Send\Mail\" />
|
||||
<Folder Include="Server\Packet\Send\Mission\" />
|
||||
<Folder Include="Server\Packet\Send\Others\" />
|
||||
<Folder Include="Server\Packet\Send\Player\" />
|
||||
<Folder Include="Server\Packet\Send\Quest\" />
|
||||
<Folder Include="Server\Packet\Send\Rogue\" />
|
||||
<Folder Include="Server\Packet\Send\Scene\" />
|
||||
<Folder Include="Server\Packet\Send\Tutorial\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SQLitePCLRaw.core" Version="2.1.8" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.1.8" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.143" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -3,7 +3,6 @@ using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Configuration;
|
||||
using EggLink.DanhengServer.WebServer;
|
||||
using EggLink.DanhengServer.Database;
|
||||
using System.Runtime.InteropServices;
|
||||
using EggLink.DanhengServer.Server;
|
||||
using EggLink.DanhengServer.Server.Packet;
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System.Buffers;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using EggLink.DanhengServer.Enums;
|
||||
using EggLink.DanhengServer.Common.Enums;
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.KcpSharp;
|
||||
using EggLink.DanhengServer.Program;
|
||||
@@ -21,16 +22,14 @@ public partial class Connection
|
||||
private readonly CancellationTokenSource CancelToken;
|
||||
public readonly IPEndPoint RemoteEndPoint;
|
||||
public SessionState State { get; set; } = SessionState.INACTIVE;
|
||||
private bool UseSecretKey { get; set; } = false;
|
||||
private byte[] SecretKey = new byte[0x1000];
|
||||
public Player? Player { get; set; }
|
||||
public PlayerInstance? Player { get; set; }
|
||||
public uint ClientTime { get; private set; }
|
||||
public long LastPingTime { get; private set; }
|
||||
private uint LastClientSeq = 10;
|
||||
public static readonly List<int> BANNED_PACKETS = [];
|
||||
private static Logger Logger = new("GameServer");
|
||||
private static readonly Logger Logger = new("GameServer");
|
||||
#if DEBUG
|
||||
private static uint LogIndex = 0;
|
||||
private static readonly Dictionary<string, string> LogMap = [];
|
||||
#endif
|
||||
public Connection(KcpConversation conversation, IPEndPoint remote)
|
||||
{
|
||||
@@ -38,11 +37,14 @@ public partial class Connection
|
||||
RemoteEndPoint = remote;
|
||||
CancelToken = new CancellationTokenSource();
|
||||
Start();
|
||||
#if DEBUG
|
||||
JsonConvert.DeserializeObject<JObject>(File.ReadAllText("LogMap.json")).Properties().ToList().ForEach(x => LogMap.Add(x.Name, x.Value.ToString()));
|
||||
#endif
|
||||
}
|
||||
|
||||
private async void Start()
|
||||
{
|
||||
Logger.Info($"New connection to {RemoteEndPoint} created with conversation id {Conversation.ConversationId}");
|
||||
Logger.Info($"New connection from {RemoteEndPoint}.");
|
||||
State = SessionState.WAITING_FOR_TOKEN;
|
||||
await ReceiveLoop();
|
||||
}
|
||||
@@ -72,14 +74,20 @@ public partial class Connection
|
||||
#if DEBUG
|
||||
public static void LogPacket(string sendOrRecv, ushort opcode, byte[] payload)
|
||||
{
|
||||
//Logger.DebugWriteLine($"{sendOrRecv}: {Enum.GetName(typeof(OpCode), opcode)}({opcode})\r\n{Convert.ToHexString(payload)}");
|
||||
Type? typ = AppDomain.CurrentDomain.GetAssemblies().
|
||||
SingleOrDefault(assembly => assembly.GetName().Name == "Shared").GetTypes().First(t => t.Name == $"{Enum.GetName(typeof(CmdId), opcode)}"); //get the type using the packet name
|
||||
MessageDescriptor? descriptor = (MessageDescriptor)typ.GetProperty("Descriptor", BindingFlags.Public | BindingFlags.Static).GetValue(null, null); // get the static property Descriptor
|
||||
IMessage? packet = descriptor.Parser.ParseFrom(payload);
|
||||
JsonFormatter? formatter = JsonFormatter.Default;
|
||||
string? asJson = formatter.Format(packet);
|
||||
Logger.Debug($"{sendOrRecv}: {Enum.GetName(typeof(CmdId), opcode)}({opcode})\r\n{asJson}");
|
||||
try
|
||||
{
|
||||
//Logger.DebugWriteLine($"{sendOrRecv}: {Enum.GetName(typeof(OpCode), opcode)}({opcode})\r\n{Convert.ToHexString(payload)}");
|
||||
Type? typ = AppDomain.CurrentDomain.GetAssemblies().
|
||||
SingleOrDefault(assembly => assembly.GetName().Name == "Common").GetTypes().First(t => t.Name == $"{LogMap[opcode.ToString()]}"); //get the type using the packet name
|
||||
MessageDescriptor? descriptor = (MessageDescriptor)typ.GetProperty("Descriptor", BindingFlags.Public | BindingFlags.Static).GetValue(null, null); // get the static property Descriptor
|
||||
IMessage? packet = descriptor.Parser.ParseFrom(payload);
|
||||
JsonFormatter? formatter = JsonFormatter.Default;
|
||||
string? asJson = formatter.Format(packet);
|
||||
Logger.Debug($"{sendOrRecv}: {LogMap[opcode.ToString()]}({opcode})\r\n{asJson}");
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.Debug($"{sendOrRecv}: {LogMap[opcode.ToString()]}({opcode})");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -131,8 +139,6 @@ public partial class Connection
|
||||
{
|
||||
byte[] gamePacket = data.ToArray();
|
||||
|
||||
// Decrypt and turn back into a packet
|
||||
//Crypto.Xor(gamePacket, UseSecretKey ? SecretKey : Crypto.DISPATCH_KEY);
|
||||
await using MemoryStream? ms = new(gamePacket);
|
||||
using BinaryReader? br = new(ms);
|
||||
|
||||
@@ -159,8 +165,10 @@ public partial class Connection
|
||||
uint payloadLength = br.ReadUInt32BE();
|
||||
byte[] header = br.ReadBytes(headerLength);
|
||||
byte[] payload = br.ReadBytes((int)payloadLength);
|
||||
|
||||
await HandlePacketAsync(opcode, header, payload);
|
||||
#if DEBUG
|
||||
LogPacket("Recv", opcode, payload);
|
||||
#endif
|
||||
HandlePacket(opcode, header, payload);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -174,7 +182,7 @@ public partial class Connection
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> HandlePacketAsync(ushort opcode, byte[] header, byte[] payload)
|
||||
private bool HandlePacket(ushort opcode, byte[] header, byte[] payload)
|
||||
{
|
||||
// Find the Handler for this opcode
|
||||
Handler? handler = EntryPoint.HandlerManager.GetHandler(opcode);
|
||||
@@ -185,7 +193,7 @@ public partial class Connection
|
||||
SessionState state = State;
|
||||
switch ((int)opcode)
|
||||
{
|
||||
case CmdId.PlayerGetTokenCsReq:
|
||||
case CmdIds.PlayerGetTokenCsReq:
|
||||
{
|
||||
if (state != SessionState.WAITING_FOR_TOKEN)
|
||||
{
|
||||
@@ -193,7 +201,7 @@ public partial class Connection
|
||||
}
|
||||
goto default;
|
||||
}
|
||||
case CmdId.PlayerLoginCsReq:
|
||||
case CmdIds.PlayerLoginCsReq:
|
||||
{
|
||||
if (state != SessionState.WAITING_FOR_LOGIN)
|
||||
{
|
||||
@@ -204,15 +212,14 @@ public partial class Connection
|
||||
default:
|
||||
break;
|
||||
}
|
||||
handler.OnHandle(header, payload);
|
||||
handler.OnHandle(this, header, payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public async Task SendPacketAsync(BasePacket packet)
|
||||
public void SendPacket(BasePacket packet)
|
||||
{
|
||||
// Test
|
||||
if (packet.CmdId <= 0)
|
||||
@@ -226,10 +233,40 @@ public partial class Connection
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
LogPacket("Send", packet.CmdId, packet.Data);
|
||||
#endif
|
||||
// Header
|
||||
byte[] packetBytes = packet.BuildPacket();
|
||||
|
||||
await Conversation.SendAsync(packetBytes, CancelToken.Token);
|
||||
#pragma warning disable CA2012
|
||||
_ = Conversation.SendAsync(packetBytes, CancelToken.Token);
|
||||
#pragma warning restore CA2012
|
||||
}
|
||||
|
||||
public void SendPacket(int cmdId)
|
||||
{
|
||||
// Test
|
||||
if (cmdId <= 0)
|
||||
{
|
||||
Logger.Debug("Tried to send packet with missing cmd id!");
|
||||
return;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can)
|
||||
if (BANNED_PACKETS.Contains(cmdId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#if DEBUG
|
||||
LogPacket("Send", (ushort)cmdId, []);
|
||||
#endif
|
||||
|
||||
// Header
|
||||
byte[] packetBytes = new BasePacket((ushort)cmdId).BuildPacket();
|
||||
|
||||
#pragma warning disable CA2012
|
||||
_ = Conversation.SendAsync(packetBytes, CancelToken.Token);
|
||||
#pragma warning restore CA2012
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace EggLink.DanhengServer.Server
|
||||
{
|
||||
public class GameSession()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using EggLink.DanhengServer.Util;
|
||||
using Google.Protobuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -6,13 +8,42 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet
|
||||
{
|
||||
public class BasePacket
|
||||
public class BasePacket(ushort cmdId)
|
||||
{
|
||||
public int CmdId;
|
||||
private const uint HEADER_CONST = 0x9d74c714;
|
||||
private const uint TAIL_CONST = 0xd7a152c8;
|
||||
|
||||
public ushort CmdId { get; set; } = cmdId;
|
||||
public byte[] Data { get; private set; } = [];
|
||||
|
||||
public void SetData(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public void SetData(IMessage message)
|
||||
{
|
||||
Data = message.ToByteArray();
|
||||
}
|
||||
|
||||
public byte[] BuildPacket()
|
||||
{
|
||||
return [];
|
||||
using MemoryStream? ms = new();
|
||||
using BinaryWriter? bw = new(ms);
|
||||
|
||||
bw.WriteUInt32BE(HEADER_CONST);
|
||||
bw.WriteUInt16BE(CmdId);
|
||||
bw.WriteUInt16BE(0);
|
||||
bw.WriteUInt32BE((uint)Data.Length);
|
||||
if (Data.Length > 0)
|
||||
{
|
||||
bw.Write(Data);
|
||||
}
|
||||
bw.WriteUInt32BE(TAIL_CONST);
|
||||
|
||||
byte[] packet = ms.ToArray();
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet
|
||||
{
|
||||
public class CmdId
|
||||
public class CmdIds
|
||||
{
|
||||
// None
|
||||
public const int None = 0;
|
||||
@@ -1,13 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet
|
||||
namespace EggLink.DanhengServer.Server.Packet
|
||||
{
|
||||
public abstract class Handler
|
||||
{
|
||||
public abstract void OnHandle(byte[] header, byte[] data);
|
||||
public abstract void OnHandle(Connection connection, byte[] header, byte[] data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet
|
||||
{
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Avatar;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Avatar
|
||||
{
|
||||
[Opcode(CmdIds.GetAvatarDataCsReq)]
|
||||
public class HandlerGetAvatarDataCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetAvatarDataScRsp(connection.Player!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Mission;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Mission
|
||||
{
|
||||
[Opcode(CmdIds.GetMissionStatusCsReq)]
|
||||
public class HandlerGetMissionStatusCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = GetMissionStatusCsReq.Parser.ParseFrom(data);
|
||||
if (req != null)
|
||||
{
|
||||
connection.SendPacket(new PacketGetMissionStatusScRsp(req));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
GameServer/Server/Packet/Recv/Player/HandlerGetBagCsReq.cs
Normal file
18
GameServer/Server/Packet/Recv/Player/HandlerGetBagCsReq.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.GetBagCsReq)]
|
||||
public class HandlerGetBagCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetBagScRsp(connection.Player!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.GetBasicInfoCsReq)]
|
||||
public class HandlerGetBasicInfoCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetBasicInfoScRsp(connection.Player!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.GetHeroBasicTypeInfoCsReq)]
|
||||
public class HandlerGetHeroBasicTypeInfoCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetHeroBasicTypeInfoScRsp(connection.Player!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.GetPlayerBoardDataCsReq)]
|
||||
public class HandlerGetPlayerBoardDataCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetPlayerBoardDataScRsp(connection.Player!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,33 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Common.Enums;
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Player;
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
using EggLink.DanhengServer.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdId.PlayerGetTokenCsReq)]
|
||||
[Opcode(CmdIds.PlayerGetTokenCsReq)]
|
||||
public class HandlerPlayerGetTokenCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(byte[] header, byte[] data)
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = PlayerGetTokenCsReq.Parser.ParseFrom(data);
|
||||
Logger.GetByClassName().Debug("OnHandle" + req.ToString());
|
||||
connection.State = SessionState.WAITING_FOR_LOGIN;
|
||||
var pd = DatabaseHelper.Instance?.GetInstance<PlayerData>(long.Parse(req.AccountUid));
|
||||
if (pd == null)
|
||||
connection.Player = new PlayerInstance()
|
||||
{
|
||||
Uid = ushort.Parse(req.AccountUid),
|
||||
};
|
||||
else
|
||||
{
|
||||
connection.Player = new PlayerInstance(pd);
|
||||
}
|
||||
connection.Player.OnLogin();
|
||||
connection.Player.Connection = connection;
|
||||
connection.SendPacket(new PacketPlayerGetTokenScRsp(connection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.PlayerHeartBeatCsReq)]
|
||||
public class HandlerPlayerHeartBeatCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = PlayerHeartbeatCsReq.Parser.ParseFrom(data);
|
||||
if (req != null)
|
||||
{
|
||||
connection.SendPacket(new PacketPlayerHeartBeatScRsp((long)req.ClientTimeMs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using EggLink.DanhengServer.Common.Enums;
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.PlayerLoginCsReq)]
|
||||
public class HandlerPlayerLoginCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.State = SessionState.ACTIVE;
|
||||
connection.SendPacket(new PacketPlayerLoginScRsp(connection));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Player
|
||||
{
|
||||
[Opcode(CmdIds.PlayerLoginFinishCsReq)]
|
||||
public class HandlerPlayerLoginFinishCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(CmdIds.PlayerLoginFinishScRsp);
|
||||
connection.SendPacket(CmdIds.GetArchiveDataScRsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using EggLink.DanhengServer.Server.Packet.Send.Scene;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Recv.Scene
|
||||
{
|
||||
[Opcode(CmdIds.GetEnteredSceneCsReq)]
|
||||
public class HandlerGetEnteredSceneCsReq : Handler
|
||||
{
|
||||
public override void OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
connection.SendPacket(new PacketGetEnteredSceneScRsp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Avatar
|
||||
{
|
||||
public class PacketGetAvatarDataScRsp : BasePacket
|
||||
{
|
||||
public PacketGetAvatarDataScRsp(PlayerInstance player) : base(CmdIds.GetAvatarDataScRsp)
|
||||
{
|
||||
var proto = new GetAvatarDataScRsp()
|
||||
{
|
||||
IsGetAll = true,
|
||||
};
|
||||
|
||||
player.AvatarManager?.AvatarData?.Avatars?.ForEach(avatar =>
|
||||
{
|
||||
proto.AvatarList.Add(avatar.ToProto());
|
||||
});
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Mission
|
||||
{
|
||||
public class PacketGetMissionStatusScRsp : BasePacket
|
||||
{
|
||||
public PacketGetMissionStatusScRsp(GetMissionStatusCsReq req) : base(CmdIds.GetMissionStatusScRsp)
|
||||
{
|
||||
var proto = new GetMissionStatusScRsp();
|
||||
|
||||
foreach (var item in req.MainMissionIdList)
|
||||
{
|
||||
proto.FinishedMainMissionIdList.Add(item);
|
||||
}
|
||||
|
||||
foreach (var item in req.SubMissionIdList)
|
||||
{
|
||||
proto.SubMissionStatusList.Add(new Proto.Mission()
|
||||
{
|
||||
Id = item,
|
||||
Status = MissionStatus.MissionFinish,
|
||||
});
|
||||
}
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
GameServer/Server/Packet/Send/Player/PacketGetBagScRsp.cs
Normal file
30
GameServer/Server/Packet/Send/Player/PacketGetBagScRsp.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketGetBagScRsp : BasePacket
|
||||
{
|
||||
public PacketGetBagScRsp(PlayerInstance player) : base(CmdIds.GetBagScRsp)
|
||||
{
|
||||
var proto = new GetBagScRsp();
|
||||
|
||||
player.InventoryManager.Data.MaterialItems.ForEach(item =>
|
||||
{
|
||||
proto.MaterialList.Add(item.ToMaterialProto());
|
||||
});
|
||||
|
||||
player.InventoryManager.Data.RelicItems.ForEach(item =>
|
||||
{
|
||||
proto.RelicList.Add(item.ToRelicProto());
|
||||
});
|
||||
|
||||
player.InventoryManager.Data.EquipmentItems.ForEach(item =>
|
||||
{
|
||||
proto.EquipmentList.Add(item.ToEquipmentProto());
|
||||
});
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketGetBasicInfoScRsp : BasePacket
|
||||
{
|
||||
public PacketGetBasicInfoScRsp(PlayerInstance player) : base(CmdIds.GetBasicInfoScRsp)
|
||||
{
|
||||
var proto = new GetBasicInfoScRsp()
|
||||
{
|
||||
CurDay = 1,
|
||||
NextRecoverTime = player.Data.NextStaminaRecover / 1000,
|
||||
GameplayBirthday = (uint)player.Data.Birthday,
|
||||
PlayerSettingInfo = new(),
|
||||
};
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketGetHeroBasicTypeInfoScRsp : BasePacket
|
||||
{
|
||||
public PacketGetHeroBasicTypeInfoScRsp(PlayerInstance player) : base(CmdIds.GetHeroBasicTypeInfoScRsp)
|
||||
{
|
||||
var proto = new GetHeroBasicTypeInfoScRsp()
|
||||
{
|
||||
Gender = player.Data.CurrentGender ?? Gender.None,
|
||||
CurBasicType = (HeroBasicType)player.Data.CurBasicType,
|
||||
};
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketGetPlayerBoardDataScRsp : BasePacket
|
||||
{
|
||||
public PacketGetPlayerBoardDataScRsp(PlayerInstance player) : base(CmdIds.GetPlayerBoardDataScRsp)
|
||||
{
|
||||
var proto = new GetPlayerBoardDataScRsp()
|
||||
{
|
||||
CurrentHeadIconId = (uint)player.Data.HeadIcon,
|
||||
Signature = player.Data.Signature,
|
||||
};
|
||||
|
||||
player.PlayerUnlockData.HeadIcons.ForEach(id =>
|
||||
{
|
||||
HeadIcon headIcon = new() { Id = (uint)id };
|
||||
proto.UnlockedHeadIconList.Add(headIcon);
|
||||
});
|
||||
|
||||
proto.DisplayAvatarVec = new();
|
||||
var pos = 0;
|
||||
player.AvatarManager.AvatarData.DisplayAvatars.ForEach(avatar =>
|
||||
{
|
||||
DisplayAvatar displayAvatar = new()
|
||||
{
|
||||
AvatarId = (uint)avatar,
|
||||
Pos = (uint)pos++,
|
||||
};
|
||||
proto.DisplayAvatarVec.DisplayAvatarList.Add(displayAvatar);
|
||||
});
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketPlayerGetTokenScRsp : BasePacket
|
||||
{
|
||||
public PacketPlayerGetTokenScRsp(Connection connection) : base(CmdIds.PlayerGetTokenScRsp)
|
||||
{
|
||||
var rsp = new PlayerGetTokenScRsp()
|
||||
{
|
||||
BlackInfo = new BlackInfo(),
|
||||
Uid = connection.Player?.Uid ?? 0,
|
||||
};
|
||||
|
||||
SetData(rsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketPlayerHeartBeatScRsp : BasePacket
|
||||
{
|
||||
public PacketPlayerHeartBeatScRsp(long clientTime) : base(CmdIds.PlayerHeartBeatScRsp)
|
||||
{
|
||||
var data = new PlayerHeartbeatScRsp()
|
||||
{
|
||||
ClientTimeMs = (ulong)clientTime,
|
||||
ServerTimeMs = (ulong)(DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond),
|
||||
};
|
||||
|
||||
SetData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketPlayerLoginScRsp : BasePacket
|
||||
{
|
||||
public PacketPlayerLoginScRsp(Connection connection) : base(CmdIds.PlayerLoginScRsp)
|
||||
{
|
||||
var rsp = new PlayerLoginScRsp()
|
||||
{
|
||||
CurTimezone = (int)TimeZoneInfo.Local.BaseUtcOffset.TotalHours,
|
||||
ServerTimestampMs = (ulong)(DateTime.Now.Ticks / 10000),
|
||||
BasicInfo = connection?.Player?.ToProto(), // should not be null
|
||||
Stamina = (uint)(connection?.Player?.Data.Stamina ?? 0),
|
||||
};
|
||||
|
||||
SetData(rsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketPlayerSyncScNotify : BasePacket
|
||||
{
|
||||
public PacketPlayerSyncScNotify() : base(CmdIds.PlayerSyncScNotify)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using EggLink.DanhengServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Player
|
||||
{
|
||||
public class PacketStaminaInfoScNotify : BasePacket
|
||||
{
|
||||
public PacketStaminaInfoScNotify(PlayerInstance player) : base(CmdIds.StaminaInfoScNotify)
|
||||
{
|
||||
var proto = new StaminaInfoScNotify()
|
||||
{
|
||||
Stamina = (uint)player.Data.Stamina,
|
||||
ReserveStamina = (uint)player.Data.StaminaReserve,
|
||||
NextRecoverTime = player.Data.NextStaminaRecover,
|
||||
};
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.Server.Packet.Send.Scene
|
||||
{
|
||||
public class PacketGetEnteredSceneScRsp : BasePacket
|
||||
{
|
||||
public PacketGetEnteredSceneScRsp() : base(CmdIds.GetEnteredSceneScRsp)
|
||||
{
|
||||
var proto = new GetEnteredSceneScRsp();
|
||||
|
||||
foreach (var excel in GameData.MapEntranceData.Values)
|
||||
{
|
||||
// Skip these
|
||||
if (excel.FinishMainMissionList.Count == 0 && excel.FinishMainMissionList.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add info
|
||||
var info = new EnteredSceneInfo()
|
||||
{
|
||||
FloorId = (uint)excel.FloorID,
|
||||
PlaneId = (uint)excel.PlaneID,
|
||||
};
|
||||
|
||||
proto.EnteredSceneInfo.Add(info);
|
||||
}
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace EggLink.DanhengServer.WebServer.Handler
|
||||
res.message = "Invalid login data";
|
||||
return new JsonResult(res);
|
||||
}
|
||||
AccountData? account = AccountData.GetAccountByUid(long.Parse(tokenData.uid)) as AccountData;
|
||||
AccountData? account = AccountData.GetAccountByUid(long.Parse(tokenData.uid));
|
||||
if (account == null)
|
||||
{
|
||||
res.retcode = -201;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EggLink.DanhengServer.WebServer.Handler
|
||||
{
|
||||
public JsonResult Handle(string uid, string token)
|
||||
{
|
||||
AccountData? account = AccountData.GetAccountByUid(long.Parse(uid)) as AccountData;
|
||||
AccountData? account = AccountData.GetAccountByUid(long.Parse(uid));
|
||||
var res = new LoginResJson();
|
||||
if (account == null || !account.DispatchToken.Equals(token))
|
||||
{
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace EggLink.DanhengServer.WebServer.Handler
|
||||
public JsonResult Handle(string account, string password, bool isCrypto)
|
||||
{
|
||||
LoginResJson res = new();
|
||||
AccountData accountData = (AccountData)AccountData.GetAccountByUserName(account);
|
||||
AccountData? accountData = AccountData.GetAccountByUserName(account);
|
||||
|
||||
if (accountData == null)
|
||||
{
|
||||
if (ConfigManager.Config.ServerOption.AutoCreateUser)
|
||||
{
|
||||
AccountHelper.CreateAccount(account, 0);
|
||||
accountData = (AccountData)AccountData.GetAccountByUserName(account);
|
||||
accountData = AccountData.GetAccountByUserName(account);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SQLitePCLRaw.core" Version="2.1.8" />
|
||||
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.1.8" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.143" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user