Advertisement
Guest User

Untitled

a guest
Jul 4th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.97 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5.  
  6. namespace Scripting
  7. {
  8.     public class AccountDatabase : IAccountDatabase
  9.     {
  10.         class ActorInstance
  11.         {
  12.             public string Name;
  13.             public string AccountName;
  14.             public bool Banned;
  15.             public bool GM;
  16.             public int ID;
  17.         }
  18.  
  19.         static string FilePath = @"Data\Server Data\Accounts\";
  20.  
  21.         // Use this to speed up searches!
  22.         static LinkedList<ActorInstance> SearchDB = new LinkedList<ActorInstance>();
  23.  
  24.         /// <summary>
  25.         /// Initialize account database.
  26.         /// </summary>
  27.         public void Initialize(AccountAddEventHandler addDelegate)
  28.         {
  29.             // Gather list of account files in account directory
  30.             // Exceptions thrown here are caught by the loading phase
  31.             string[] Files = Directory.GetFiles(FilePath, "*.dat");
  32.  
  33.             // Pre-load each account
  34.             foreach (string FileName in Files)
  35.             {
  36.                 // Read header
  37.                 using (BBBinaryReader Reader = new BBBinaryReader(File.OpenRead(FileName)))
  38.                 {
  39.  
  40.                     string Username = Path.GetFileNameWithoutExtension(FileName);
  41.                     string Password = Reader.ReadBBString();
  42.                     string Email = Reader.ReadBBString();
  43.                     bool GM = Reader.ReadBoolean();
  44.                     bool Banned = Reader.ReadBoolean();
  45.  
  46.                     // Read through actor data and pull out instances
  47.                     // This isn't necessary, but it saves a massive amount of CPU
  48.                     // and IO read time when processing Offline/All ActorInfo requests
  49.                     int ID = 0;
  50.                     while (!Reader.Eof)
  51.                     {
  52.                         int ActorLength = Reader.ReadInt32();
  53.                         byte[] SerializedAI = Reader.ReadBytes(ActorLength);
  54.  
  55.                         int ScriptsLength = Reader.ReadInt32();
  56.                         byte[] SerializedScripts = Reader.ReadBytes(ScriptsLength);
  57.  
  58.                         ActorInstance AI = new ActorInstance();
  59.                         AI.AccountName = Username;
  60.                         AI.Banned = Banned;
  61.                         AI.GM = GM;
  62.  
  63.                         // The serialized actor data begins with a 32-bit ID followed by a namestring with an 8-bit length
  64.                         byte Length = SerializedAI[4];
  65.                         AI.Name = ASCIIEncoding.ASCII.GetString(SerializedAI, 5, Length);
  66.                         AI.ID = ID;
  67.  
  68.                         SearchDB.AddLast(AI);
  69.                         ++ID;
  70.                     }
  71.  
  72.                     Reader.Close();
  73.  
  74.                     // New account base
  75.                     addDelegate.Invoke(
  76.                         new AccountBase(Username, Password, Email, GM, Banned),
  77.                         true);
  78.                 }
  79.  
  80.  
  81.  
  82.             }
  83.         }
  84.  
  85.         /// <summary>
  86.         /// Add an account to the account database
  87.         /// </summary>
  88.         public void Add(AccountBase account, AccountAddEventHandler completionDelegate)
  89.         {
  90.             // Check
  91.             if (account == null)
  92.             {
  93.                 completionDelegate.Invoke(account, false);
  94.                 return;
  95.             }
  96.  
  97.             // Attempt to write file
  98.             using (BBBinaryWriter Writer = new BBBinaryWriter(File.Open(Path.Combine(FilePath, account.Username + ".dat"), FileMode.Create)))
  99.             {
  100.  
  101.                 // Write account header
  102.                 Writer.WriteBBString(account.Password);
  103.                 Writer.WriteBBString(account.Email);
  104.                 Writer.Write(account.IsGM);
  105.                 Writer.Write(account.IsBanned);
  106.  
  107.                 // Done
  108.                 Writer.Close();
  109.             }
  110.  
  111.             completionDelegate.Invoke(account, true);
  112.         }
  113.  
  114.         /// <summary>
  115.         /// Load an accounts actors.
  116.         /// </summary>
  117.         public void Load(AccountBase account, AccountLoadEventHandler completionDelegate)
  118.         {
  119.             // Check
  120.             if (account == null)
  121.             {
  122.                 completionDelegate.Invoke(account, null);
  123.                 return;
  124.             }
  125.  
  126.             // Attempt to read account
  127.             using (BBBinaryReader Reader = new BBBinaryReader(File.OpenRead(Path.Combine(FilePath, account.Username + ".dat"))))
  128.             {
  129.  
  130.                 // Read account header
  131.                 Reader.ReadBBString(); // Password
  132.                 Reader.ReadBBString(); // Email
  133.                 Reader.ReadBoolean(); // GM
  134.                 Reader.ReadBoolean(); // Banned
  135.  
  136.                 // Setup output
  137.                 LoadCompleteEventArgs Args = new LoadCompleteEventArgs(account);
  138.  
  139.                 // Read in actor data
  140.                 while (!Reader.Eof)
  141.                 {
  142.                     int ActorLength = Reader.ReadInt32();
  143.                     byte[] SerializedAI = Reader.ReadBytes(ActorLength);
  144.  
  145.                     int ScriptsLength = Reader.ReadInt32();
  146.                     byte[] SerializedScripts = Reader.ReadBytes(ScriptsLength);
  147.  
  148.                     Args.ActorInstances.Add(new ActorInstanceData(SerializedAI, SerializedScripts));
  149.                 }
  150.  
  151.                 // Close reader
  152.                 Reader.Close();
  153.  
  154.                 // Run completion callback
  155.                 completionDelegate.Invoke(account, Args);
  156.             }
  157.         }
  158.  
  159.         /// <summary>
  160.         /// Save an accounts actors.
  161.         /// </summary>
  162.         public void Save(AccountBase account, int index, ActorInstanceData data)
  163.         {
  164.             // Check
  165.             if (account == null)
  166.                 return;
  167.  
  168.             // Setup output
  169.             List<ActorInstanceData> ActorInstances = new List<ActorInstanceData>();
  170.  
  171.             // Read existing data (so we can insert this actor instance)
  172.             // Attempt to read account
  173.             using (BBBinaryReader Reader = new BBBinaryReader(File.OpenRead(Path.Combine(FilePath, account.Username + ".dat"))))
  174.             {
  175.  
  176.                 // Read account header
  177.                 Reader.ReadBBString(); // Password
  178.                 Reader.ReadBBString(); // Email
  179.                 Reader.ReadBoolean(); // GM
  180.                 Reader.ReadBoolean(); // Banned
  181.  
  182.                 // Read in actor data
  183.                 while (!Reader.Eof)
  184.                 {
  185.                     int ActorLength = Reader.ReadInt32();
  186.                     byte[] SerializedAI = Reader.ReadBytes(ActorLength);
  187.  
  188.                     int ScriptsLength = Reader.ReadInt32();
  189.                     byte[] SerializedScripts = Reader.ReadBytes(ScriptsLength);
  190.  
  191.                     ActorInstances.Add(new ActorInstanceData(SerializedAI, SerializedScripts));
  192.                 }
  193.  
  194.                 // Close reader
  195.                 Reader.Close();
  196.             }
  197.  
  198.             // Replace existing actor data with our new data
  199.             if (index >= ActorInstances.Count)
  200.             {
  201.                 ActorInstances.Add(data);
  202.  
  203.                 if (data != null)
  204.                 {
  205.                     ActorInstance AI = new ActorInstance();
  206.                     AI.AccountName = account.Username;
  207.                     AI.Banned = account.IsBanned;
  208.                     AI.GM = account.IsGM;
  209.                     AI.ID = ActorInstances.Count - 1;
  210.  
  211.                     // The serialized actor data begins with a 32-bit ID followed by a namestring with an 8-bit length
  212.                     byte Length = data.SerializedAI[4];
  213.                     AI.Name = ASCIIEncoding.ASCII.GetString(data.SerializedAI, 5, Length);
  214.  
  215.                     SearchDB.AddLast(AI);
  216.                 }
  217.             }
  218.             else
  219.             {
  220.                 ActorInstances[index] = data;
  221.  
  222.                 LinkedListNode<ActorInstance> AINode = SearchDB.First;
  223.                 while (AINode != null)
  224.                 {
  225.                     ActorInstance AI = AINode.Value;
  226.  
  227.                     if (AI.ID == index && AI.AccountName == account.Username)
  228.                     {
  229.                         if (data == null)
  230.                         {
  231.                             SearchDB.Remove(AINode);
  232.                             break;
  233.                         }
  234.                         else
  235.                         {
  236.                             // The serialized actor data begins with a 32-bit ID followed by a namestring with an 8-bit length
  237.                             byte Length = data.SerializedAI[4];
  238.                             string Name = ASCIIEncoding.ASCII.GetString(data.SerializedAI, 5, Length);
  239.  
  240.                             AI.Name = Name;
  241.                             AI.Banned = account.IsBanned;
  242.                             AI.GM = account.IsGM;
  243.                             break;
  244.                         }
  245.                     }
  246.                    
  247.                     AINode = AINode.Next;
  248.                 }
  249.             }
  250.  
  251.             // Attempt to write file
  252.             using (BBBinaryWriter Writer = new BBBinaryWriter(File.Open(Path.Combine(FilePath, account.Username + ".dat"), FileMode.Create)))
  253.             {
  254.  
  255.                 // Write account header
  256.                 Writer.WriteBBString(account.Password);
  257.                 Writer.WriteBBString(account.Email);
  258.                 Writer.Write(account.IsGM);
  259.                 Writer.Write(account.IsBanned);
  260.  
  261.                 // Actor data
  262.                 foreach (ActorInstanceData AID in ActorInstances)
  263.                 {
  264.                     // Input 'data' will be null on deletion, so we skip that when writing.
  265.                     if (AID != null)
  266.                     {
  267.                         Writer.Write(AID.SerializedAI.Length);
  268.                         Writer.Write(AID.SerializedAI);
  269.  
  270.                         Writer.Write(AID.SerializedScripts.Length);
  271.                         Writer.Write(AID.SerializedScripts);
  272.                     }
  273.                 }
  274.  
  275.                 // Done
  276.                 Writer.Close();
  277.             }
  278.         }
  279.  
  280.         /// <summary>
  281.         ///
  282.         /// </summary>
  283.         public void Update()
  284.         {
  285.  
  286.         }
  287.  
  288.         /// <summary>
  289.         /// Perform a search for the given actor name to see if it exists.
  290.         /// </summary>
  291.         /// <param name="request">Handle of request object.</param>
  292.         /// <param name="completionDelegate">Callback for completion of search.</param>
  293.         public void OnActorInfoRequest(ActorInfoRequest request, AccountActorInfoRequestHandler completionDelegate)
  294.         {
  295.             foreach (ActorInstance AI in SearchDB)
  296.             {
  297.                 if (AI.Name.Equals(request.ActorName, StringComparison.CurrentCultureIgnoreCase))
  298.                 {
  299.                     completionDelegate.Invoke(request, AI.Name, AI.AccountName, AI.Banned, AI.GM);
  300.                     return;
  301.                 }
  302.             }
  303.  
  304.             // Failed!
  305.             completionDelegate.Invoke(request, null, null, false, false);
  306.         }
  307.  
  308.     }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement