Example #1
0
File: Map.cs Project: bilwis/SH2RL
        /// <summary>
        /// This function iterates through the content of a cell and unloads every object into DB.
        /// </summary>
        /// <param name="c">The cell to be unloaded.</param>
        private void unloadCellContent(Cell c)
        {
            SQLiteCommand command = new SQLiteCommand(dbconn);

            //Clear all exisiting cell content from DB
            command.CommandText = "DELETE FROM cell_contents WHERE cell_id='" + c.CellID + "'";
            command.ExecuteNonQuery();

            //Setup Transaction
            SQLiteTransaction tr = dbconn.BeginTransaction();
            command.Transaction = tr;

            //Save all items by retrieving all guids and iterating through
            //them. (Can't iterate through an IEnumerable and change it within the iteration!)
            string[] keys = ItemList.GetKeys().ToArray<string>();
            for (int i = 0; i < keys.Length; i++)
            {
                Item kv = ItemList[keys[i]];
                if (kv.X <= (c.X + wm.CELL_WIDTH) && kv.X >= c.X)
                {
                    if (kv.Y <= (c.Y + wm.CELL_HEIGHT) && kv.Y >= c.Y)
                    {
                        if (kv.Z <= (c.Z + wm.CELL_DEPTH) && kv.Z >= c.Z)
                        {
                            command.CommandText = "INSERT INTO cell_contents (cell_id, content_type, content_guid) VALUES ('" + c.CellID + "', '" + (int)Util.DBLookupType.Item + "', '" + kv.GUID + "')";
                            command.ExecuteNonQuery();
                            UnloadItem(kv.GUID);
                        }
                    }
                }
            }

            //Save all creatures (refer item saving above)
            keys = new string[CreatureList.Count];
            keys = CreatureList.GetKeys().ToArray<string>();

            for (int i = 0; i < keys.Length; i++)
            {
                Creature cr = CreatureList[keys[i]];
                //Only save AICreatures though (only "Creature" should be the player itself)
                if (cr.GetType() == typeof(AICreature))
                {
                    if (cr.X <= (c.X + wm.CELL_WIDTH) && cr.X >= c.X)
                    {
                        if (cr.Y <= (c.Y + wm.CELL_HEIGHT) && cr.Y >= c.Y)
                        {
                            if (cr.Z <= (c.Z + wm.CELL_DEPTH) && cr.Z >= c.Z)
                            {
                                command.CommandText = "INSERT INTO cell_contents (cell_id, content_type, content_guid) VALUES ('" + c.CellID + "', '" + (int)Util.DBLookupType.AICreature + "', '" + cr.GUID + "')";
                                command.ExecuteNonQuery();
                                UnloadAICreature(cr.GUID);
                            }
                        }
                    }
                }
            }

            //Commit, cleanup
            tr.Commit();
            command.Dispose();
        }
Example #2
0
        /// <summary>
        /// Initializes a new WorldMap object, which provides cell retrieval and terrain generation functions.
        /// </summary>
        /// <param name="seed">The map seed.</param>
        /// <param name="dbconn">The connection to the object database.</param>
        /// <param name="parameters">The parameters for terrain generation.</param>
        public WorldMap(uint seed, SQLiteConnection dbconn, int[] parameters)
        {
            //Initialization
            this.dbconn = dbconn;
            this.seed = seed;
            rand = new TCODRandom(seed, TCODRandomType.ComplementaryMultiplyWithCarry);
            noise = new TCODNoise(2, rand);

            CELL_WIDTH = parameters[0];
            CELL_HEIGHT = parameters[1];
            CELL_DEPTH = parameters[2];

            CELLS_X = parameters[3];
            CELLS_Y = parameters[4];
            CELLS_Z = parameters[5];

            GLOBAL_WIDTH = CELLS_X * CELL_WIDTH;
            GLOBAL_HEIGHT = CELLS_Y * CELL_HEIGHT;
            GLOBAL_DEPTH = CELLS_Z * CELL_DEPTH;

            GROUND_LEVEL = parameters[6];

            //Create Cells
            cells = new Cell[CELLS_X, CELLS_Y, CELLS_Z];
            int id = 0;
            for (int x = 0; x < CELLS_X; x++)
            {
                for (int y = 0; y < CELLS_Y; y++)
                {
                    for (int z = 0; z < CELLS_Z; z++)
                    {
                        cells[x, y, z] = new Cell(x * CELL_WIDTH, y * CELL_HEIGHT, z * CELL_DEPTH, id, this);
                        id++;
                    }
                }
            }

            //Create Tiles
            makeDefaultTileSetup();
            loadTileDict();
            makeTestDiffs();
        }
Example #3
0
File: Map.cs Project: bilwis/SH2RL
        /// <summary>
        /// This function handles the shifting, loading and unloading of cells.
        /// </summary>
        /// <param name="rel_x">The relative position of the new center cell (X).</param>
        /// <param name="rel_y">The relative position of the new center cell (Y).</param>
        /// <param name="rel_z">The relative position of the new center cell (Z).</param>
        /// <returns>true if successful, false if not</returns>
        private bool loadNewCells(int rel_x, int rel_y, int rel_z)
        {
            //NOTE: The following code seems really complicated when you look at it (it's very "clean" and "efficient", ergo totally not human readable!)
            //I will try to explain the meaning of each loop/vector by using the example "MOVE INTO CELL TO THE TOP (x-1) LEFT (y-1) OF THE CURRENT CENTER".
            //This would correspond to the parameters: rel_x = 0, rel_y = 0, rel_z = 1.
            //When moving into the "top left", the program must do the following operations:
            //  0) CHECK if the move is legal.
            //     The program checks if all the cells that would have to be loaded (see III) ) actually exist, if not, it denies the move by
            //     returning false.
            //  I) UNLOAD the "old" cells, i.e. the cells that now fall out of the 3x3 "loaded cells" grid, to free up the memory they're holding.
            //     For our example, that means all the "lowermost" and the "rightmost" cells must be unloaded.
            // II) SHIFT the remaining original cells.
            //     Since we moved to the top left, the former top left (TL) cell is now the central cell. The top top (TT), the left left (LL)
            //     and the former center (C) can also be preserved, but must be shifted too.
            //     In the example the "shifting vector" (in the code: shift_vect) is {-1,-1,0} and the
            //     "limiting vector" (in the code: limit_vect) is {0,0,-1}, meaning that all cells where X != 0 AND Y != 0
            //     (Z doesn't matter, it's "taken along", hence the -1 in the limit_vect) are overwritten with the cell at {X+(-1), Y+(-1), Z+0}
            //     This shifts the TL, the TT, the LL and the C to the C, the RR, the BB and the BR, respectively.
            //III) LOAD the new cells.
            //     All that remains is that we load the new cells, in our example case these would be the new TL, TT, TR, LL and BL, because we
            //     moved both on the x- and on the y-axis. Again, this is handled by the shifting and the limiting vector. The limiting vector
            //     now (figuratively) becomes the "limited"-vector (still {0,0,-1}) because only cells where X == 0 OR Y == 0 are newly loaded.
            //     The loading uses the GetAdjacentCell method of the WorldMap-Class and utilized the shifting vector.

            //FOR DEBUG PURPOSES
            Stopwatch sw = new Stopwatch();
            sw.Start();

            //1. Setup Vectors
            int[] vect = { rel_x, rel_y, rel_z };
            int[] unload_vect = { -1, -1, -1 };
            int[] shift_vect = { 0, 0, 0 };

            //1.1 Initialize the "unload vector"
            for (int i = 0; i < 3; i++)
            {
                if (vect[i] == 0)
                    unload_vect[i] = 2; //If shift on the "i"-Axis is -1, or "0" in the relative coords,
                //then the cells with "i+1" must be unloaded.

                if (vect[i] == 1)
                    unload_vect[i] = -1;//If shift on the "i"-Axis is 0, or "1" in the relative coords,
                //then this axis doesn't warrant any action.

                if (vect[i] == 2)
                    unload_vect[i] = 0; //If shift on the "i"-Axis is +1, or "2" in the relative coords,
                //then the cells with "i-1" must be unloaded.

            }

            //1.2 Convert the "relative" coordinates of the new cell (stored in vect[]) into the necessary
            //    shifting operation on each axis.
            for (int i = 0; i < 3; i++)
            {
                if (vect[i] == 0)
                    shift_vect[i] = -1;

                if (vect[i] == 1)
                    shift_vect[i] = 0;

                if (vect[i] == 2)
                    shift_vect[i] = 1;
            }

            //1.3 This vector stores the information necessary to prevent the algorithm from trying
            //    to shift non-loaded cells into the cell array. It is also used (conversely) to load
            //    only the cells that need loading.
            int[] limit_vect = { -1, -1, -1 };
            for (int i = 0; i < 3; i++)
            {
                if (vect[i] == 0)
                    limit_vect[i] = 0;

                if (vect[i] == 1)
                    limit_vect[i] = -1;

                if (vect[i] == 2)
                    limit_vect[i] = 2;
            }

            //---------------------------------------------------------------------------------
            //0) RUN PRE-ALGORITHM CHECK if cells to be loaded actually exists,
            //   if not, deny the move.
            //
            //   NOTE: This has to be run previous to every other operation, because the
            //   initial state is not backed up for memory reasons, so "undo" later is impossible
            //---------------------------------------------------------------------------------
            bool[] causes_validation = { false, false, false };
            for (int x = 0; x < 3; x++)
            {
                if (x == limit_vect[0] || limit_vect[0] == -1)
                {
                    causes_validation[0] = true;
                }
                for (int y = 0; y < 3; y++)
                {
                    if (y == limit_vect[1] || limit_vect[1] == -1)
                    {
                        causes_validation[1] = true;
                    }
                    for (int z = 0; z < 3; z++)
                    {
                        if (z == limit_vect[2] || limit_vect[2] == -1)
                        {
                            causes_validation[2] = true;
                        }

                        if (!causes_validation[0] && !causes_validation[1] && !causes_validation[2])
                            continue;

                        if (wm.GetAdjacentCell(shift_vect[0], shift_vect[1], shift_vect[2], cells[x, y, z]) == null)
                            return false;

                        causes_validation[2] = false;
                    }
                    causes_validation[1] = false;
                }
                causes_validation[0] = false;
            }

            initialized = false;

            //---------------------------------------------------------------------------------
            //I) UNLOAD OLD CELLS, i.e. the cells on the "far end" of the coordinate block
            //---------------------------------------------------------------------------------
            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    for (int z = 0; z < 3; z++)
                    {
                        if (x == unload_vect[0] || y == unload_vect[1] || z == unload_vect[2])
                        {
                            unloadCellContent(cells[x, y, z]);
                            cells[x, y, z].Unload();
                        }
                    }
                }
            }

            //---------------------------------------------------------------------------------
            //II) SHIFT remaining original cells in the appropriate direction
            //---------------------------------------------------------------------------------

            //Setup temporary cells array (this is needed to ensure neither loading or shifting
            // is done on cells that have already been shifted or loaded)
            Cell[, ,] tempcells = new Cell[3, 3, 3];
            Array.Copy(cells, tempcells, cells.Length);

            //Do the shifting
            for (int x = 0; x < 3; x++)
            {
                if (x != limit_vect[0])
                {
                    for (int y = 0; y < 3; y++)
                    {
                        if (y != limit_vect[1])
                        {
                            for (int z = 0; z < 3; z++)
                            {
                                if (z != limit_vect[2])
                                {
                                    cells[x, y, z] = tempcells[x + shift_vect[0], y + shift_vect[1], z + shift_vect[2]];
                                }
                            }
                        }
                    }
                }
            }

            //---------------------------------------------------------------------------------
            //III) LOAD new cells
            //---------------------------------------------------------------------------------
            //Do the loading
            int derp = 0;
            bool[] cause_load = { false, false, false };
            for (int x = 0; x < 3; x++)
            {
                if (x == limit_vect[0])
                {
                    cause_load[0] = true;
                }
                for (int y = 0; y < 3; y++)
                {
                    if (y == limit_vect[1])
                    {
                        cause_load[1] = true;
                    }
                    for (int z = 0; z < 3; z++)
                    {
                        if (z == limit_vect[2])
                        {
                            cause_load[2] = true;
                        }

                        if (!cause_load[0] && !cause_load[1] && !cause_load[2])
                            continue;

                        loaded[x, y, z] = false;
                        load_after[x, y, z] = true;
                        cells[x, y, z] = wm.GetAdjacentCell(shift_vect[0], shift_vect[1], shift_vect[2], tempcells[x, y, z]);
                        if (Program.game.MULTITHREADED_LOADING)
                        {
                            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
                            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(backgroundWorker_DoWork);
                            bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

                            bw.RunWorkerAsync(cells[x, y, z]);
                        }
                        else
                        {
                            cells[x, y, z].Load();
                            loadCellContent(cells[x, y, z].CellID);
                        }
                        derp++;
                        cause_load[2] = false;
                    }
                    cause_load[1] = false;
                }
                cause_load[0] = false;
            }

            tempcells = null;

            sw.Stop();
            _out.SendMessage(derp + " new cells loaded: Loading took " + sw.ElapsedMilliseconds + "ms.");

            return true;
        }
Example #4
0
        /// <summary>
        /// This function returns the cell at the given relative position of the given cell.
        /// </summary>
        public Cell GetAdjacentCell(int dx, int dy, int dz, Cell c)
        {
            int rx = (c.X / CELL_WIDTH); //TRUNCATED!
            int ry = (c.Y/ CELL_HEIGHT);
            int rz = (c.Z / CELL_DEPTH);

            if (rx + dx >= 0 && ry + dy >= 0 && rz + dz >= 0)
            {
                try
                {
                    return cells[rx + dx, ry + dy, rz + dz];
                }
                catch
                {
                    return null;
                }
            }

            return null;
        }