Beispiel #1
0
        public static bool UnregisterObject(Guid go)
        {
            ServerGameObject sgo = null;

            AllGameObjects.TryRemove(go, out sgo);
            return(sgo != null);
        }
Beispiel #2
0
 public static bool RegisterObject(ServerGameObject go)
 {
     if(AllGameObjects.TryAdd(go.UID, go))
     {
         GameEvents.FireEvent(GameEventType.ObjectLoaded, go, null);
         return true;
     }
     return false;
 }
Beispiel #3
0
 public static bool RegisterObject(ServerGameObject go)
 {
     if (AllGameObjects.TryAdd(go.UID, go))
     {
         GameEvents.FireEvent(GameEventType.ObjectLoaded, go, null);
         return(true);
     }
     return(false);
 }
Beispiel #4
0
        /// <summary>
        /// Gets a reference to a server game object currently in memory, i.e. previously loaded from the DB.
        /// </summary>
        /// <param name="id">id of the object being returned</param>
        /// <returns></returns>
        public ServerGameObject GetItem(Guid id, ServerGameObjectManager gom, bool includeDeleted = false)
        {
            ServerGameObject sgo = gom.GetGameObjectFromId(id) as ServerGameObject;

            if (sgo == null || (!includeDeleted && sgo.IsDeleted))
            {
                return(null);
            }

            return(sgo);
        }
Beispiel #5
0
        /// <summary>
        /// Gets called as the Item is being created in the Database.  If you have additional DB tasks
        /// to add, now is the time.  Use the supplied connection and transaction objects.  The connection should already
        /// be open.
        /// Do NOT close the connection and do NOT commit /rollback the transaction.  Simply return true or false if
        /// you want the creation to be committed or not.
        /// </summary>
        /// <param name="ItemId">the id of the Item to delete</param>
        /// <param name="owner">the owner of the Item to delete</param>
        /// <param name="permaPurge">should the data be permanently purged</param>
        /// <param name="reason">reason for service log</param>
        /// <param name="rsltMsg">a message saying why deletion failed, if any</param>
        /// <param name="con">the connection object to use for additional database work in relation to Item creation</param>
        /// <param name="tran">the transaction object to use for additional database work in relation to Item creation</param>
        /// <returns>return false if you do not want the transaction to be committed, which will also cause Item creation to fail</returns>

        /*
         * public bool DeleteItem(Guid ItemId, ServerUser player, bool permaPurge, string reason, ref string rsltMsg)
         * {
         *   SqlConnection con = null;
         *   SqlTransaction tran = null;
         *
         *   try
         *   {
         *       if (DB.Instance.Item_Delete(player.ID, ItemId, permaPurge, reason, out tran, out con))
         *       {
         *           tran.Commit();
         *           return true;
         *       }
         *       else
         *       {
         *           if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
         *           {
         *               if (tran != null)
         *               {
         *                   tran.Rollback();
         *               }
         *           }
         *       }
         *   }
         *   catch (Exception exc)
         *   {
         *       if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
         *       {
         *           if (tran != null)
         *           {
         *               tran.Rollback();
         *           }
         *       }
         *       return false;
         *   }
         *   finally
         *   {
         *       if (con != null)
         *       {
         *           con.Close();
         *           con.Dispose();
         *           con = null;
         *       }
         *
         *       if (tran != null)
         *       {
         *           tran.Dispose();
         *           tran = null;
         *       }
         *   }
         *
         *   return false;
         * }
         */

        /// <summary>
        /// Saves/updates the Item to the DB
        /// </summary>
        /// <param name="owner">owning account</param>
        /// <param name="id">the id for the Item to get</param>
        /// <returns></returns>
        public bool SaveItem(ServerGameObject item, string owner, ref string rsultMsg)
        {
            if (item == null)
            {
                return(false);
            }

            SqlConnection  con  = null;
            SqlTransaction tran = null;

            if (item.IsTransient)
            {
                rsultMsg = "Transient objects can't be saved.";
                return(false);
            }
            try
            {
                Guid cown = Guid.Empty;
                if (DB.Instance.Item_Save(item, owner, out rsultMsg, out tran, out con))
                {
                    tran.Commit();
                }
                else
                {
                    if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                    {
                        if (tran != null)
                        {
                            tran.Rollback();
                        }
                    }
                    rsultMsg = "Can't save Item. " + rsultMsg;
                    return(false);
                }
            }
            catch (Exception e)
            {
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }
            return(true);
        }
        public override void RemoveGameObject(IGameObject actor)
        {
            if (actor == null)
            {
                return;
            }

            ServerGameObject sgo = actor as ServerGameObject;

            base.RemoveGameObject(actor);
            MasterObjectManager.UnregisterObject(actor.UID);

            if (actor is WispPlayer && OnPlayerRemoved != null)
            {
                OnPlayerRemoved(actor as WispPlayer);
            }
        }
        public override void RegisterGameObject(IGameObject actor, Guid context)
        {
            if (actor == null)
            {
                return;
            }

            base.RegisterGameObject(actor, context);
            ServerGameObject sgo = actor as ServerGameObject;

            MasterObjectManager.RegisterObject(sgo);

            if (actor is WispPlayer && OnPlayerAdded != null)
            {
                OnPlayerAdded(actor as WispPlayer);
            }
        }
Beispiel #8
0
        /// <summary>
        /// creates a Item object, but does not persist it.
        /// </summary>
        /// <param name="properties">Item properties to add</param>
        /// <param name="owner">the owning user</param>
        /// <param name="context">Any user defined context - could be a game room, an owning server, etc.  GameObjectManager keeps sub-lists of games based on context ID. Use GUID.Empty for none. </param>
        /// <returns></returns>
        public ServerGameObject CreateNewItem(string itemTemplate, Guid context, ServerGameObjectManager gom, string owningServer)
        {
            ServerGameObject sgo = CreateItemShell(itemTemplate);

            if (sgo == null)
            {
                return(null);
            }

            sgo.IsGhost = true;
            // Instantiate the inner GameObject
            sgo.Context = context;
            // Add the needed bits
            sgo.UID          = Guid.NewGuid();
            sgo.CreatedOn    = DateTime.UtcNow;
            sgo.OwningServer = owningServer;
            gom.RegisterGameObject(sgo, context);
            return(sgo);
        }
Beispiel #9
0
        /// <summary>
        /// Delete an object from the world.
        /// </summary>
        /// <param name="id"></param>
        public void DeleteItem(Guid id, Guid accountDeleting, string reason, ServerGameObjectManager gom)
        {
            ServerGameObject sgo = null;

            if (gom != null)
            {
                GetItem(id, gom);
            }
            else
            {
                string msg = "";
                sgo = LoadItem(id, true, "", ref msg, null);
            }

            if (sgo != null)
            {
                sgo.IsDeleted      = true;
                sgo.DeleteReason   = reason;
                sgo.AccountDeleted = accountDeleting;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Creates the item, based on the template, but doesn't register it with the object manager, nor does it persist it
        /// </summary>
        /// <param name="template"></param>
        /// <returns></returns>
        public ServerGameObject CreateItemShell(string template)
        {
            Template t = null;

            if (!Template.Templates.TryGetValue(template.ToLower(), out t))
            {
                return(null);
            }

            uint             hash = Factory.GetStableHash(t.Class);
            ServerGameObject sgo  = Factory.Instance.CreateObject(hash) as ServerGameObject;

            if (sgo == null)
            {
                Log1.Logger("Server").Error("Tried to instantiate game object of type " + t.Class + ", but the Factory could not find that type.  Was it registered?");
                return(null);
            }

            foreach (uint script in t.Scripts)
            {
                GameObjectScript gos = GameObjectScript.GetScript(script);
                if (gos == null)
                {
                    Log1.Logger("ObjectError").Error("Unable to instantiate GameObjectScript [" + script + "] for template [" + t.Name + "]. On game object [" + sgo.UID.ToString() + "].");
                    continue;
                }

                sgo.Scripts.AttachScript(gos);
            }

            sgo.Properties.UpdateWithValues(t.Properties);
            sgo.Stats.UpdateWithValues(t.Stats);
            sgo.ItemTemplate   = t.Name;
            sgo.GameObjectType = t.GameObjectType;
            sgo.IsStatic       = t.IsStatic;
            sgo.StackCount     = t.StackCount;
            sgo.IsTransient    = t.IsTransient;

            return(sgo);
        }
Beispiel #11
0
        /// <summary>
        /// Read an item from the database.  if @lockedBy is set to null or empty string it is assumed that you are not trying to take ownership of the loaded object and are opening it for read-only 
        /// purposes.  Setting the @lockedBy parameter to a server ID indicates that that server has ownership of the object.  Objects cannot be saved except by the lock's owner.  
        /// </summary>
        /// <param name="db"></param>
        /// <param name="item"></param>
        /// <param name="ItemId"></param>
        /// <param name="includeDeleted"></param>
        /// <param name="loadedBy"></param>
        /// <param name="tran"></param>
        /// <param name="con"></param>
        /// <returns></returns>
        public static bool Item_Load(this DB db, out ServerGameObject item, Guid ItemId, bool includeDeleted, string lockedBy, out SqlTransaction tran, out SqlConnection con)
        {
            tran = null;
            con = null;

            bool result = true;

            con = DB.GameDataConnection;
            SqlCommand cmd = DB.GetCommand(con, "Items_Get", true);

            cmd.Parameters.Add(new SqlParameter("@ItemId", ItemId));
            cmd.Parameters.Add(new SqlParameter("@includeDeleted", includeDeleted));
            cmd.Parameters.Add(new SqlParameter("@lockedBy", lockedBy));

            SqlParameter pout = new SqlParameter("@resultCode", 0);
            pout.Direction = ParameterDirection.Output;
            cmd.Parameters.Add(pout);

            SqlDataReader reader = null;
            Guid context = Guid.Empty;
            item = null;

            try
            {
                int idColumn = 1;
                int valueColumn = 2;
                int nameColumn = 3;
                con.Open();

                tran = con.BeginTransaction(IsolationLevel.Serializable);
                cmd.Connection = con;
                cmd.Transaction = tran;

                reader = cmd.ExecuteReader();
                int count = 0;
                bool isStatic = false;

                if (reader.HasRows) // any items to read?
                {
                    ServerGameObject loadedItem = null;
                    if (reader.Read()) // read item data from Item Master Rable
                    {
                        string templateNum = reader.GetString(1);
                        loadedItem = ItemUtil.Instance.CreateItemShell(templateNum);

                        bool isDeleted = reader.GetByte(2) == 1;
                        loadedItem.IsDeleted = isDeleted;
                        // int GOT = reader.GetInt32(3); // set by template in CreateItemShell
                        loadedItem.UID = reader.GetGuid(0);
                        //loadedItem.ItemTemplate = templateNum; // set by template in CreateItemShell
                        // loadedItem.GameObjectType = (GOT)GOT;// set by template in CreateItemShell
                        loadedItem.CreatedOn = reader.GetDateTimeUtc(4);
                        //isStatic = reader.GetByte(9) == 1; // set by template in CreateItemShell
                        loadedItem.StackCount = reader.GetInt32(9);
                        loadedItem.Owner = reader.GetGuid(10);

                        if (!reader.IsDBNull(5))
                        {
                            loadedItem.OwningServer = reader.GetString(5);
                        }

                        loadedItem.Context = reader.GetGuid(6);
                        if (loadedItem.TypeHash != (uint)reader.GetInt64(7))
                        {
                            Log1.Logger("Server").Error("Tried loading game object [" + loadedItem.UID.ToString() + "]. Type hash was inconsistent with database.)");
                        }

                        if (!isStatic && !reader.IsDBNull(8))
                        {
                            byte[] binData = (byte[])reader["BinData"]; // works good if there's not a ton of data
                            loadedItem.Deserialize(binData, new Pointer());

                            /*
                            long dataSize = reader.GetBytes(8, 0, null, 0, 0);

                            byte[] buffer = new byte[1024];
                            var dataRemaining = dataSize;
                            while (dataRemaining > 0)
                            {
                                int bytesToRead = (int)(buffer.Length < dataRemaining ? buffer.Length : dataRemaining);
                                //fill the buffer
                                reader.GetBytes(1, dataSize - dataRemaining, buffer, 0, bytesToRead);
                                Util.Copy(buffer, 0, binData, (int)dataSize - (int)dataRemaining, bytesToRead);
                                dataRemaining -= bytesToRead;
                            }
                            */
                        }
                    }

                    //if (!isStatic)
                    {
                        reader.NextResult(); // grab item properties
                        bool attribsDone = false;

                        while (!attribsDone)
                        {
                            //reader.NextResult();
                            count++;

                            if (count == 5)
                            {
                                // Finished reading item attributes.  Go on to the next item.
                                attribsDone = true;
                            }

                            if (!reader.HasRows)
                            {
                                reader.NextResult();
                                continue;
                            }

                            IGameObject ci = loadedItem;
                            switch (count)
                            {
                                case 1: // Float
                                    while (reader.Read())
                                    {
                                        string name = reader.IsDBNull(nameColumn) ? "" : reader.GetString(nameColumn);
                                        ci.Properties.SetProperty(name, (int)reader.GetInt32(idColumn), (float)reader.GetDouble(valueColumn));
                                    }
                                    break;
                                case 2: // Int
                                    while (reader.Read())
                                    {
                                        string name = reader.IsDBNull(nameColumn) ? "" : reader.GetString(nameColumn);
                                        ci.Properties.SetProperty(name, (int)reader.GetInt32(idColumn), reader.GetInt32(valueColumn));
                                    }
                                    break;
                                case 3: // Long
                                    while (reader.Read())
                                    {
                                        string name = reader.IsDBNull(nameColumn) ? "" : reader.GetString(nameColumn);
                                        ci.Properties.SetProperty(name, (int)reader.GetInt32(idColumn), reader.GetInt64(valueColumn));
                                    }
                                    break;
                                case 4: // String
                                    while (reader.Read())
                                    {
                                        string name = reader.IsDBNull(nameColumn) ? "" : reader.GetString(nameColumn);
                                        ci.Properties.SetProperty(name, (int)reader.GetInt32(idColumn), reader.GetString(valueColumn));
                                    }
                                    break;
                                case 5: // Stats
                                    //reader.NextResult(); // read past the Item id
                                    while (reader.Read())
                                    {
                                        Stat s = new Stat();
                                        s.StatID = reader.GetInt32(reader.GetOrdinal("StatID"));

                                        double cValue = reader.GetDouble(reader.GetOrdinal("CurrentValue"));
                                        double mValue = reader.GetDouble(reader.GetOrdinal("MaxValue"));
                                        double mnValue = reader.GetDouble(reader.GetOrdinal("MinValue"));

                                        Stat proto = StatManager.Instance[s.StatID];
                                        if (proto == null)
                                        {
                                            Log1.Logger("Server.Stats").Error("Item_Load attempted to read stat ID [" + s.StatID + "] which was not defined in the Stats.xml config file. Stat not added to Item.");
                                            continue;
                                        }

                                        s.MinValue = (float)mnValue;
                                        s.MaxValue = (float)mValue;
                                        s.ForceValue((float)cValue);

                                        s.Description = proto.Description;
                                        s.DisplayName = proto.DisplayName;
                                        s.Group = proto.Group;

                                        ci.Stats.AddStat(s);
                                    }
                                    break;
                            }

                            reader.NextResult();
                        } // while reader has next result for item properties
                    } // if not static item
                    item = loadedItem;
                } // while reader has rows
            }
            catch (Exception e)
            {
                Log1.Logger("Server").Error("[DATABASE ERROR Item_Load] : " + e.Message);
                result = false;
            }
            finally
            {
                if (reader != null && !reader.IsClosed)
                {
                    reader.Close();
                }
            }
            return result;
        }
Beispiel #12
0
        public static bool Item_Create(this DB db, ServerGameObject go, string owner, out string msg, out SqlTransaction tran, out SqlConnection con)
        {
            if(go.IsTransient)
            {
                con = null;
                tran = null;
                msg = "Transient objects can't be saved to the database.";
                return false;
            }

            tran = null;
            bool result = true;
            msg = "";

            con = DB.GameDataConnection;
            SqlCommand cmd = DB.GetCommand(con, "Items_Create", true);

            SqlParameter pout = new SqlParameter("@resultCode", 0);
            pout.Direction = ParameterDirection.Output;
            cmd.Parameters.Add(pout);

            cmd.Parameters.Add(new SqlParameter("@GOT", (int)go.GameObjectType));
            cmd.Parameters.Add(new SqlParameter("@UID", go.UID));
            cmd.Parameters.Add(new SqlParameter("@createdOn", go.CreatedOn));
            cmd.Parameters.Add(new SqlParameter("@template", go.ItemTemplate));
            cmd.Parameters.Add(new SqlParameter("@owner", owner));
            cmd.Parameters.Add(new SqlParameter("@context", go.Context));
            cmd.Parameters.Add(new SqlParameter("@typeHash", (long)go.TypeHash));

            Pointer dataPointer = new Pointer();
            byte[] bindata = new byte[1024];
            go.Serialize(ref bindata, dataPointer);

            // Combine envelope and body into final data gram
            byte[] trimData = new byte[dataPointer.Position];
            Util.Copy(bindata, 0, trimData, trimData.Length, dataPointer.Position);

            cmd.Parameters.Add(new SqlParameter("@binData", trimData));
            cmd.Parameters.Add(new SqlParameter("@stackCount", go.StackCount));
            cmd.Parameters.Add(new SqlParameter("@isStatic", go.IsStatic));
            cmd.Parameters.Add(new SqlParameter("@objectOwner", go.Owner));

            if (!go.IsStatic)
            {
                SqlParameter ints = new SqlParameter("@intProperties", ItemIntPropertiesToTable(go.Properties.GetAllPropertiesOfKind(PropertyKind.Int32), go.UID));
                ints.SqlDbType = SqlDbType.Structured;
                cmd.Parameters.Add(ints);

                SqlParameter floats = new SqlParameter("@floatProperties", ItemFloatPropertiesToTable(go.Properties.GetAllPropertiesOfKind(PropertyKind.Single), go.UID));
                floats.SqlDbType = SqlDbType.Structured;
                cmd.Parameters.Add(floats);

                SqlParameter longs = new SqlParameter("@longProperties", ItemLongPropertiesToTable(go.Properties.GetAllPropertiesOfKind(PropertyKind.Int64), go.UID));
                longs.SqlDbType = SqlDbType.Structured;
                cmd.Parameters.Add(longs);

                SqlParameter strings = new SqlParameter("@stringProperties", ItemStringPropertiesToTable(go.Properties.GetAllPropertiesOfKind(PropertyKind.String), go.UID));
                strings.SqlDbType = SqlDbType.Structured;
                cmd.Parameters.Add(strings);

                SqlParameter statsParm = new SqlParameter("@stats", ItemStatsToTable(go.Stats.AllStats, go.UID));
                statsParm.SqlDbType = SqlDbType.Structured;
                cmd.Parameters.Add(statsParm);
            }

            try
            {
                con.Open();
                tran = con.BeginTransaction(IsolationLevel.ReadCommitted);
                cmd.Connection = con;
                cmd.Transaction = tran;

                cmd.ExecuteNonQuery();
                long val = (long)cmd.Parameters[0].Value;
                result = val > 0;

                switch (val)
                {
                    case -1:
                    case 0:
                        msg = "Server was unable to created Item.";
                        break;
                    case 1:
                        msg = "Item created.";
                        break;
                }

                // -1 = unknown error creating Item
                //  0 = unknown error crating Item starting stats
                //  1 = Item created successfully
            }
            catch (Exception e)
            {
                Log1.Logger("Server").Error("[DATABASE ERROR] : " + e.Message);
                result = false;
            }
            finally
            {
                /*
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }

                 * Calling method must close connection. this is to allow API users to append to the Item creation method and commit the transaction
                 before closing the connection.*/
            }

            return result;
        }
Beispiel #13
0
        private static DataTable GameObjectToTable(ServerGameObject input, DataTable table = null)
        {
            if (table == null)
            {
                table = new DataTable("ItemTable");

                table.Columns.Add("Template", typeof(string));
                table.Columns.Add("CreatedOn", typeof(DateTime));
                table.Columns.Add("GOT", typeof(int));
                table.Columns.Add("UID", typeof(Guid));
                table.Columns.Add("Owner", typeof(string));
                table.Columns.Add("Context", typeof(Guid));
                table.Columns.Add("TypeHash", typeof(long));
                table.Columns.Add("BinData", typeof(byte[]));
                table.Columns.Add("IsStatic", typeof(byte));
                table.Columns.Add("StackCount", typeof(int));
                table.Columns.Add("ObjectOwner", typeof(Guid));
            }

            DataRow r = table.NewRow();
            r["Template"] = input.ItemTemplate;
            r["CreatedOn"] = input.CreatedOn;
            r["GOT"] = (int)input.GameObjectType;
            r["UID"] = input.UID;
            r["Owner"] = input.OwningServer;
            r["Context"] = input.Context;
            r["TypeHash"] = input.TypeHash;

            Pointer dataPointer = new Pointer();
            byte[] bindata = new byte[1024];
            input.Serialize(ref bindata, dataPointer);

            // Combine envelope and body into final data gram
            byte[] trimData = new byte[dataPointer.Position];
            Util.Copy(bindata, 0, trimData, trimData.Length, dataPointer.Position);

            r["BinData"] = trimData;

            r["StackCount"] = input.StackCount;
            r["IsStatic"] = input.IsStatic;
            r["ObjectOwner"] = input.Owner;
            table.Rows.Add(r);

            return table;
        }
Beispiel #14
0
        private static DataTable GameObjectToDeleteRow(ServerGameObject input, DataTable table = null)
        {
            if (table == null)
            {
                table = new DataTable("DeleteTable");

                table.Columns.Add("ItemID", typeof(Guid));
                table.Columns.Add("PermaPurge", typeof(bool));
                table.Columns.Add("Account", typeof(Guid));
                table.Columns.Add("DeleteReason", typeof(string));
            }

            DataRow r = table.NewRow();
            r["ItemID"] = input.UID;
            r["PermaPurge"] = false;
            r["Account"] = input.AccountDeleted;
            r["DeleteReason"] = input.DeleteReason;

            table.Rows.Add(r);

            return table;
        }
Beispiel #15
0
        /// <summary>
        /// Loads an Item from the DB
        /// </summary>
        /// <param name="owner">owning account</param>
        /// <param name="id">the id for the Item to get</param>
        /// <returns></returns>
        public ServerGameObject LoadItem(Guid id, bool includeDeleted, string lockedByServerId, ref string rsultMsg, ServerGameObjectManager gom)
        {
            if (id == Guid.Empty)
            {
                return(null);
            }



            SqlConnection    con  = null;
            SqlTransaction   tran = null;
            ServerGameObject sgo  = null;

            if (gom != null)
            {
                sgo = gom.GetGameObjectFromId(id) as ServerGameObject;
                if (sgo != null)
                {
                    return(sgo);
                }
            }


            try
            {
                Guid cown = Guid.Empty;
                if (DB.Instance.Item_Load(out sgo, id, includeDeleted, lockedByServerId, out tran, out con))
                {
                    ((ServerGameObject)sgo).IsDirty = false;
                    ((ServerGameObject)sgo).IsGhost = false;

                    tran.Commit();

                    bool isDeleted = false;
                    isDeleted = ((ServerGameObject)sgo).IsDeleted;

                    if (!isDeleted && lockedByServerId != null && lockedByServerId.Length > 0)
                    {
                        if (gom != null)
                        {
                            gom.RegisterGameObject(sgo, sgo.Context);
                        }
                    }
                }
                else
                {
                    rsultMsg = "Item doesn't exist.";
                    return(null);
                }
            }
            catch (Exception e)
            {
                return(null);
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }

            return(sgo);
        }
Beispiel #16
0
        /// <summary>
        /// Creates a new Item in the DB using the Item's template XML file as a basis for stats and properties.  If you want to override any of the default
        /// properties, pass in the appropriate ItemProperties property bag.
        /// </summary>
        /// <param name="msg">an error message, if any</param>
        /// <returns></returns>
        public bool PersistNewItem(ServerGameObject ci, string owner, ref string msg)
        {
            SqlConnection  con  = null;
            SqlTransaction tran = null;

            if (ci != null && ci.IsTransient)
            {
                msg = "Transient objects can't be saved.";
                return(false);
            }

            try
            {
                if (ValidateItemCreateRequest(ci, ref msg))
                {
                    if (DB.Instance.Item_Create(ci, owner, out msg, out tran, out con))
                    {
                        tran.Commit();
                        return(true);
                    }
                    else
                    {
                        if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                        {
                            if (tran != null)
                            {
                                tran.Rollback();
                            }
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                {
                    if (tran != null)
                    {
                        tran.Rollback();
                    }
                }
                return(false);
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }

                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }

            return(false);
        }