The CampaignDatabase class encapsulates support for interacting with the StoreCampaignObject and RetrieveCampaignObject script functions. It allows CLR code to be registered to handle specific calls to both of these script functions, via the StoreCampaignDatabaseEvent and RetrieveCampaignDatabaseEvent events, respectively. These two events allow code to either receive a serialized, GFF-format version of a game object, or to instantiate a game object from a GFF-format serialized buffer.
        /// <summary>
        /// This function is called when RetrieveCampaignObject("VDB_", ..)
        /// is invoked.
        /// </summary>
        /// <param name="sender">Unused.</param>
        /// <param name="e">Supplies event data.</param>
        public static void CampaignDatabase_RetrieveItemModifyEvent(object sender, CampaignDatabase.RetrieveCampaignDatabaseEventArgs e)
        {
            if (!e.CampaignName.StartsWith("ItMod"))
                return;

            e.GFF = new byte[0];
            if (ALFA.Shared.Modules.InfoStore.ModifiedGff.Keys.Contains(e.VarName))
            {
                using (MemoryStream s = new MemoryStream())
                {
                    ALFA.Shared.Modules.InfoStore.ModifiedGff[e.VarName].Save(s);
                    e.GFF = s.ToArray();
                }
            }
        }
        /// <summary>
        /// This function is called when StoreCampaignObject("VDB_", ..)
        /// is invoked.
        /// </summary>
        /// <param name="sender">Unused.</param>
        /// <param name="e">Supplies event data.</param>
        public static void CampaignDatabase_StoreItemModifyEvent(object sender, CampaignDatabase.StoreCampaignDatabaseEventArgs e)
        {
            if (!e.CampaignName.StartsWith("ItMod"))
                return;

            if (ALFA.Shared.Modules.InfoStore.ModifiedGff.Keys.Contains(e.VarName))
            {
                ALFA.Shared.Modules.InfoStore.ModifiedGff[e.VarName] = new GFFFile(e.GFF);
            }
            else
            {
                ALFA.Shared.Modules.InfoStore.ModifiedGff.Add(e.VarName, new GFFFile(e.GFF));
            }

            e.Handled = true;
        }
            /// <summary>
            /// StoreCampaignObject hook.  Called when the server script
            /// function StoreCampaignObject is called by any script.
            /// </summary>
            /// <param name="CodeBaseObject">Supplies the code base this
            /// pointer.</param>
            /// <param name="CampaignName">Supplies the campaign name.</param>
            /// <param name="VarName">Supplies the variable name.</param>
            /// <param name="PlayerName">Supplies the player name.</param>
            /// <param name="Cls">Always supplies the value 'O'.</param>
            /// <param name="Data">Supplies the raw GFF buffer.</param>
            /// <param name="Size">Supplies the count of raw GFF bytes in the
            /// data buffer.</param>
            /// <returns>True if the object was stored, else false if the
            /// object was not stored.
            private Int32 AddBinaryDataHook(IntPtr CodeBaseObject, IntPtr CampaignName, IntPtr VarName, IntPtr PlayerName, Byte Cls, IntPtr Data, UInt32 Size)
            {
                string CampaignNameStr = ServerInterop.ReadCExoString(CampaignName);

                //
                // If the campaign is the virtual database, call registered
                // event handlers.
                //

                if (CampaignNameStr.StartsWith("VDB_"))
                {
                    try
                    {
                        StoreCampaignDatabaseEventArgs EventArgs;
                        string VarNameStr    = ServerInterop.ReadCExoString(VarName);
                        string PlayerNameStr = ServerInterop.ReadCExoString(PlayerName);
                        byte[] GFF           = new byte[(int)Size];

                        Marshal.Copy(Data, GFF, 0, (int)Size);

                        EventArgs = new StoreCampaignDatabaseEventArgs(CampaignNameStr.Substring(4), VarNameStr, PlayerNameStr, GFF);
                        CampaignDatabase.StoreCampaignDatabaseEvent(null, EventArgs);

                        return(EventArgs.Handled ? 1 : 0);
                    }
                    catch (Exception e)
                    {
                        Logger.Log("CampaignDatabaseHook.AddBinaryDataHook: Exception: {0}", e);
                        return(0);
                    }
                }

                //
                // Pass through to the original server implementation that uses
                // the standard campaign database.
                //

                return(CCodeBase_AddBinaryData_OriginalDelegate(CodeBaseObject, CampaignName, VarName, PlayerName, Cls, Data, Size));
            }
            /// <summary>
            /// This function is called when StoreCampaignObject("VDB_", ..)
            /// is invoked.
            /// </summary>
            /// <param name="sender">Unused.</param>
            /// <param name="e">Supplies event data.</param>
            void CampaignDatabase_StoreCampaignDatabaseEvent(object sender, CampaignDatabase.StoreCampaignDatabaseEventArgs e)
            {
                //
                // Interested only in VDB_File_<Campaign>.
                //

                if (!e.CampaignName.StartsWith("File_"))
                    return;

                string DirectoryName = e.CampaignName.Substring(5);

                if (!SystemInfo.IsSafeFileName(DirectoryName))
                    return;
                if (!SystemInfo.IsSafeFileName(e.VarName))
                    return;

                try
                {
                    DirectoryName = DatabaseStoreDirectory + DirectoryName;
                    Directory.CreateDirectory(DirectoryName);

                    string FileName = String.Format("{0}{1}{2}.GFF", DirectoryName, Path.DirectorySeparatorChar, e.VarName);

                    File.WriteAllBytes(FileName, e.GFF);
                }
                catch (Exception ex)
                {
                    ALFA.Shared.Logger.Log("CampaignObjectFileStore.CampaignDatabase_RetrieveCampaignDatabaseEvent({0}): Exception: {1}", DirectoryName, ex);
                    return;
                }
                catch
                {
                    return;
                }

                e.Handled = true;
            }
            /// <summary>
            /// RetrieveCampaignObject hook.  Called when the server script
            /// function RetrieveCampaignObject is called by any script.
            /// </summary>
            /// <param name="CodeBaseObject">Supplies the code base this
            /// pointer.</param>
            /// <param name="CampaignName">Supplies the campaign name.</param>
            /// <param name="VarName">Supplies the variable name.</param>
            /// <param name="PlayerName">Supplies the player name.</param>
            /// <param name="Cls">Always receives 'O'.</param>
            /// <param name="Size">Receives the size of the restored object GFF
            /// data.</param>
            /// <returns>An unmanaged pointer on the server heap that contains
            /// the raw GFF data for the object.  IntPtr.Zero if there is no
            /// data to restore.</returns>
            private IntPtr GetBinaryDataHook(IntPtr CodeBaseObject, IntPtr CampaignName, IntPtr VarName, IntPtr PlayerName, out Byte Cls, out UInt32 Size)
            {
                string CampaignNameStr = ServerInterop.ReadCExoString(CampaignName);

                //
                // If the campaign is the virtual database, call registered
                // event handlers.
                //

                if (CampaignNameStr.StartsWith("VDB_"))
                {
                    Cls = (byte)'O';

                    try
                    {
                        RetrieveCampaignDatabaseEventArgs EventArgs;
                        string VarNameStr    = ServerInterop.ReadCExoString(VarName);
                        string PlayerNameStr = ServerInterop.ReadCExoString(PlayerName);

                        EventArgs = new RetrieveCampaignDatabaseEventArgs(CampaignNameStr.Substring(4), VarNameStr, PlayerNameStr);
                        CampaignDatabase.RetrieveCampaignDatabaseEvent(null, EventArgs);

                        //
                        // If no handler instantiated a GFF, then return no
                        // data found.  Otherwise, allocate a buffer from the
                        // unmanaged server heap, and copy the contents of the
                        // GFF into the heap buffer and return the heap buffer.
                        //

                        if (EventArgs.GFF == null || EventArgs.GFF.Length == 0)
                        {
                            Size = 0;
                            return(IntPtr.Zero);
                        }
                        else
                        {
                            IntPtr GFFBuffer = IntPtr.Zero;

                            try
                            {
                                GFFBuffer = ServerInterop.AllocateServerHeap((uint)EventArgs.GFF.Length);
                                Marshal.Copy(EventArgs.GFF, 0, GFFBuffer, EventArgs.GFF.Length);
                                Size = (uint)EventArgs.GFF.Length;

                                return(GFFBuffer);
                            }
                            catch (Exception e)
                            {
                                Logger.Log("CampaignDatabaseHook.GetBinaryDataHook: Exception: {0}", e);

                                if (GFFBuffer != IntPtr.Zero)
                                {
                                    ServerInterop.FreeServerHeap(GFFBuffer);
                                    GFFBuffer = IntPtr.Zero;
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Log("CampaignDatabaseHook.GetBinaryDataHook: Exception: {0}", e);

                        Size = 0;
                        return(IntPtr.Zero);
                    }
                }

                //
                // Pass through to the original server implementation that uses
                // the standard campaign database.
                //

                return(CCodeBase_GetBinaryData_OriginalDelegate(CodeBaseObject, CampaignName, VarName, PlayerName, out Cls, out Size));
            }