PSO2SERVER/Server/Database/ServerEf.cs

351 lines
10 KiB
C#
Raw Normal View History

2024-09-10 00:31:40 +08:00
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.IO;
using System.Runtime.InteropServices;
2024-09-10 00:31:40 +08:00
using MySql.Data.EntityFramework;
using PSO2SERVER.Models;
2024-12-02 20:43:28 +08:00
using PSO2SERVER.Protocol;
using static PSO2SERVER.Models.CharacterStruct;
2024-09-10 00:31:40 +08:00
2024-09-10 01:13:20 +08:00
namespace PSO2SERVER.Database
2024-09-10 00:31:40 +08:00
{
2024-09-20 21:58:37 +08:00
public class Account
{
[Key]
public int AccountId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Nickname { get; set; }
public string SettingsIni { get; set; }
2024-12-03 18:17:43 +08:00
public int TextLang { get; set; }
public int VoiceLang { get; set; }
public int TextLang2 { get; set; }
public int LangLang { get; set; }
public string LanguageCode { get; set; }
2024-09-20 21:58:37 +08:00
}
2024-12-03 18:17:43 +08:00
public class AccountNetInterFace
{
[Key]
public int id { get; set; }
public int AccountId { get; set; }
public string Username { get; set; }
public int State { get; set; }
public string Mac { get; set; }
}
public class AccountSystemInfo
2024-09-10 00:31:40 +08:00
{
[Key]
public int id { get; set; }
public int AccountId { get; set; }
2024-09-10 00:31:40 +08:00
public string Username { get; set; }
public string CpuInfo { get; set; }
public string VideoInfo { get; set; }
public long Vram { get; set; }
public long TotalRam { get; set; }
public int Unk1 { get; set; }
public int Unk2 { get; set; }
public string WindowsVersion { get; set; }
public string WindowSize { get; set; }
public string AudioDevices { get; set; }
public string Unk4 { get; set; }
public string VideoDriver { get; set; }
public long TotalDiskSpace { get; set; }
public long FreeDiskSpace { get; set; }
2024-09-10 00:31:40 +08:00
}
2024-12-02 20:43:28 +08:00
public class Character
{
// Probably more info than this
[Key, Column(Order = 1)]
public int CharacterID { get; set; }
[Key, Column(Order = 2)]
public int AccountID { get; set; }
public int Unk1 { get; set; }
public int VoiceType { get; set; }
public short Unk2 { get; set; }
public short VoicePitch { get; set; }
public string Name { get; set; }
public LooksParam Looks { get; set; }
public byte[] LooksBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Looks);
return w.ToArray();
}
set
{
Looks = Helper.ByteArrayToStructure<LooksParam>(value);
}
}
public int Unk3 { get; set; }
public JobParam Jobs { get; set; }
public byte[] JobsBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Jobs);
return w.ToArray();
}
set
{
Jobs = Helper.ByteArrayToStructure<JobParam>(value);
}
}
public byte[] Unk4 { get; set; } = new byte[148];
2024-12-02 20:43:28 +08:00
public byte[] Fulldata { get; set; }
public PSO2Items[] EquipedItems { get; set; } = new PSO2Items[10];
2024-12-02 20:43:28 +08:00
public byte[] EquipedItemsBinary
{
get
{
PacketWriter w = new PacketWriter();
foreach (var item in EquipedItems)
{
w.WriteStruct(item);
}
return w.ToArray();
}
set
{
// 每个PSO2Items的大小包含uuid、ItemId、Items
int itemSize = Marshal.SizeOf(typeof(PSO2Items));
// 计算字节数组中包含多少个PSO2Items对象
int itemCount = value.Length / itemSize;
// 创建一个新的数组来存储这些对象
EquipedItems = new PSO2Items[itemCount];
// 逐个反序列化
for (int i = 0; i < itemCount; i++)
{
// 提取对应的字节块
byte[] itemBytes = new byte[itemSize];
Array.Copy(value, i * itemSize, itemBytes, 0, itemSize);
// 使用Helper.ByteArrayToStructure来反序列化每个PSO2Items对象
EquipedItems[i] = Helper.ByteArrayToStructure<PSO2Items>(itemBytes);
}
}
}
2024-12-07 01:44:49 +08:00
public byte[] BuildCharacterByteArray()
{
PacketWriter writer = new PacketWriter();
// 序列化字段CharacterID, AccountID, Unk1, VoiceType, Unk2, VoicePitch
writer.Write((uint)CharacterID);
writer.Write((uint)AccountID);
writer.Write((uint)Unk1);
writer.Write((uint)VoiceType);
writer.Write((ushort)Unk2);
writer.Write(VoicePitch);
// 序列化 Name (假设固定长度字符串16个字节UTF-16 编码)
writer.WriteFixedLengthUtf16(Name, 0x10);
// 序列化 Looks
writer.WriteStruct(Looks);
// 序列化 Unk3
writer.Write((uint)Unk3);
// 序列化 Jobs
writer.WriteStruct(Jobs);
// 序列化 Unk4
writer.WriteBytes(0, 148);
2024-12-07 01:44:49 +08:00
// 最后返回字节流
return writer.ToArray();
}
public virtual Account Account { get; set; }
2024-12-02 20:43:28 +08:00
}
2024-12-03 18:17:43 +08:00
public class NPC
{
[Key, Column(Order = 1)]
public int EntityID { get; set; }
[Key, Column(Order = 2)]
public string ZoneName { get; set; }
public string NPCName { get; set; }
public float RotX { get; set; }
public float RotY { get; set; }
public float RotZ { get; set; }
public float RotW { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float PosZ { get; set; }
2024-12-06 21:49:29 +08:00
public int is_active { get; set; }
2024-12-03 18:17:43 +08:00
}
public class GameObject
{
[Key, Column(Order = 1)]
public int ObjectID { get; set; }
[Key, Column(Order = 2)]
public string ZoneName { get; set; }
public string ObjectName { get; set; }
public byte[] ObjectFlags { get; set; }
public float RotX { get; set; }
public float RotY { get; set; }
public float RotZ { get; set; }
public float RotW { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float PosZ { get; set; }
}
public class ServerInfo
{
[Key, MaxLength(255)]
public string Info { get; set; }
public string Setting { get; set; }
}
public class Teleport
{
[Key, Column(Order = 1)]
public string ZoneName { get; set; }
[Key, Column(Order = 2)]
public int ObjectID { get; set; }
public float RotX { get; set; }
public float RotY { get; set; }
public float RotZ { get; set; }
public float RotW { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float PosZ { get; set; }
}
2024-09-10 00:31:40 +08:00
[DbConfigurationType(typeof(MySqlEFConfiguration))]
2024-09-10 01:13:20 +08:00
public class ServerEf : DbContext
2024-09-10 00:31:40 +08:00
{
public DbSet<Account> Accounts { get; set; }
2024-12-03 18:17:43 +08:00
public DbSet<AccountNetInterFace> AccountsNetInterFaces { get; set; }
public DbSet<AccountSystemInfo> AccountsSystemInfoes { get; set; }
2024-09-10 00:31:40 +08:00
public DbSet<Character> Characters { get; set; }
public DbSet<GameObject> GameObjects { get; set; }
2024-12-03 18:17:43 +08:00
public DbSet<NPC> NPCs { get; set; }
public DbSet<ServerInfo> ServerInfoes { get; set; }
public DbSet<Teleport> Teleports { get; set; }
2024-09-10 00:31:40 +08:00
2024-09-10 01:13:20 +08:00
public ServerEf()
2024-09-10 00:31:40 +08:00
: base(
string.Format("server={0};port={1};database={2};username={3};password={4}",
2024-09-10 01:13:20 +08:00
ServerApp.Config.DatabaseAddress,
ServerApp.Config.DatabasePort,
ServerApp.Config.DatabaseName,
ServerApp.Config.DatabaseUsername,
ServerApp.Config.DatabasePassword)
2024-09-10 00:31:40 +08:00
)
{
}
public void SetupDB()
{
try
{
foreach (
var f in
Directory.EnumerateFiles(Directory.GetCurrentDirectory() + "/Resources/sql/scripts/", "*.sql"))
{
2024-09-10 01:36:26 +08:00
Logger.WriteInternal("[DBC] 执行数据库脚本 {0}", f);
2024-09-10 00:31:40 +08:00
Database.ExecuteSqlCommand(File.ReadAllText(f));
}
var revision = ServerInfoes.Find("Revision");
2024-09-10 00:31:40 +08:00
if (revision == null)
{
revision = new ServerInfo { Info = "Revision", Setting = "0" };
ServerInfoes.Add(revision);
2024-09-10 00:31:40 +08:00
//TODO Possibly move this somewhere else?
Database.ExecuteSqlCommand("ALTER TABLE Accounts AUTO_INCREMENT=10000000");
2024-09-10 00:31:40 +08:00
}
SaveChanges();
2024-09-10 01:36:26 +08:00
Logger.WriteInternal("[DBC] 加载数据集修订的数据库 {0}", revision.Setting);
2024-09-10 00:31:40 +08:00
}
catch (Exception ex)
{
Logger.WriteException("数据库异常", ex);
}
}
2024-09-11 16:33:10 +08:00
public bool TestDatabaseConnection2()
2024-09-10 00:31:40 +08:00
{
try
{
2024-09-10 01:13:20 +08:00
using (var context = new ServerEf())
2024-09-10 00:31:40 +08:00
{
// 执行一个简单的查询来测试数据库连接
context.Database.ExecuteSqlCommand("SELECT 1");
2024-09-10 12:58:38 +08:00
Logger.WriteInternal("[DBT] 数据库连接成功。");
2024-09-10 00:31:40 +08:00
return true;
}
}
catch (Exception ex)
{
2024-09-11 16:33:10 +08:00
Logger.WriteException("数据库连接异常", ex);
return false;
}
}
public bool TestDatabaseConnection()
{
try
{
using (var context = new ServerEf())
{
context.Database.Initialize(force: false);
Logger.WriteInternal("[DBT] 数据库连接成功。");
return true;
}
}
catch (Exception ex)
{
Logger.WriteException("数据库连接异常", ex);
2024-09-10 00:31:40 +08:00
return false;
}
}
}
}