PSO2SERVER/Server/Database/ServerEf.cs

356 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.IO;
using System.Runtime.InteropServices;
using MySql.Data.EntityFramework;
using PSO2SERVER.Models;
using PSO2SERVER.Protocol;
using static PSO2SERVER.Models.CharacterStruct;
namespace PSO2SERVER.Database
{
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; }
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; }
public int IsGM { get; set; }
public int PacketType { get; set; }
public string PSNID { get; set; }
}
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
{
[Key]
public int id { get; set; }
public int AccountId { get; set; }
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; }
}
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];
public byte[] Fulldata { get; set; }
public PSO2Items[] EquipedItems { get; set; } = new PSO2Items[10];
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);
}
}
}
public uint Playe_time { get; set; }
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);
// 最后返回字节流
return writer.ToArray();
}
public virtual Account Account { get; set; }
}
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; }
public int is_active { get; set; }
}
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; }
}
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class ServerEf : DbContext
{
public DbSet<Account> Accounts { get; set; }
public DbSet<AccountNetInterFace> AccountsNetInterFaces { get; set; }
public DbSet<AccountSystemInfo> AccountsSystemInfoes { get; set; }
public DbSet<Character> Characters { get; set; }
public DbSet<GameObject> GameObjects { get; set; }
public DbSet<NPC> NPCs { get; set; }
public DbSet<ServerInfo> ServerInfoes { get; set; }
public DbSet<Teleport> Teleports { get; set; }
public ServerEf()
: base(
string.Format("server={0};port={1};database={2};username={3};password={4}",
ServerApp.Config.DatabaseAddress,
ServerApp.Config.DatabasePort,
ServerApp.Config.DatabaseName,
ServerApp.Config.DatabaseUsername,
ServerApp.Config.DatabasePassword)
)
{
}
public void SetupDB()
{
try
{
foreach (
var f in
Directory.EnumerateFiles(Directory.GetCurrentDirectory() + "/Resources/sql/scripts/", "*.sql"))
{
Logger.WriteInternal("[DBC] 执行数据库脚本 {0}", f);
Database.ExecuteSqlCommand(File.ReadAllText(f));
}
var revision = ServerInfoes.Find("Revision");
if (revision == null)
{
revision = new ServerInfo { Info = "Revision", Setting = "0" };
ServerInfoes.Add(revision);
//TODO Possibly move this somewhere else?
Database.ExecuteSqlCommand("ALTER TABLE Accounts AUTO_INCREMENT=10000000");
}
SaveChanges();
Logger.WriteInternal("[DBC] 加载数据集修订的数据库 {0}", revision.Setting);
}
catch (Exception ex)
{
Logger.WriteException("数据库异常", ex);
}
}
public bool TestDatabaseConnection2()
{
try
{
using (var context = new ServerEf())
{
// 执行一个简单的查询来测试数据库连接
context.Database.ExecuteSqlCommand("SELECT 1");
Logger.WriteInternal("[DBT] 数据库连接成功。");
return true;
}
}
catch (Exception ex)
{
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);
return false;
}
}
}
}