예제 #1
0
        public static MobSpawner CreateMobSpawner(MobSpawners dbMobSpawner, MobSpawnTableSet spawnTableSet)
        {
            MobSpawner newMobSpawner = new MobSpawner();

            newMobSpawner.m_room_key              = new RoomKey(dbMobSpawner.GameID, dbMobSpawner.RoomX, dbMobSpawner.RoomY, dbMobSpawner.RoomZ);
            newMobSpawner.m_mob_spawner_id        = dbMobSpawner.MobSpawnerID;
            newMobSpawner.m_position              = new Point3d((float)dbMobSpawner.X, (float)dbMobSpawner.Y, (float)dbMobSpawner.Z);
            newMobSpawner.m_remaining_spawn_count = dbMobSpawner.RemainingSpawnCount;
            newMobSpawner.m_random_seed           = dbMobSpawner.RandomSeed;
            newMobSpawner.m_spawn_table           = spawnTableSet.GetMobSpawnTableByID(dbMobSpawner.MobSpawnerTableID);

            return(newMobSpawner);
        }
예제 #2
0
        public static MobSpawner CreateMobSpawner(RoomKey roomKey, MobSpawnerTemplate template, MobSpawnTableSet spawnTableSet, Random rng)
        {
            MobSpawner newMobSpawner = new MobSpawner();

            newMobSpawner.m_room_key = new RoomKey(roomKey);
            newMobSpawner.m_mob_spawner_id = -1; // spawner ID not set until this gets saved into the DB
            newMobSpawner.m_position = new Point3d(template.Position);
            newMobSpawner.m_remaining_spawn_count = RNGUtilities.RandomInt(rng, 0, template.MaxSpawnCount);
            newMobSpawner.m_random_seed = rng.Next();
            newMobSpawner.m_spawn_table = spawnTableSet.GetMobSpawnTableByName(template.SpawnTableName);

            return newMobSpawner;
        }
예제 #3
0
        public bool ValidateDungeons(Command command)
        {
            bool success = true;
            string result= SuccessMessages.GENERAL_SUCCESS;

            RoomTemplateSet roomTemplateSet = new RoomTemplateSet();
            MobTypeSet mobTypeSet = new MobTypeSet();
            MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet();
            int game_id_min = 0;
            int game_id_max = 100000; // Int32.MaxValue; This will take ~100 days to finish all 2 billion  dungeons
            string connection_string = "";

            string dumpGeometryPath = "";

            if (command.HasArgumentWithName("C"))
            {
                connection_string = command.GetTypedArgumentByName<CommandArgument_String>("C").ArgumentValue;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: Missing expected connection string parameter");
                success = false;
            }

            if (command.HasArgumentWithName("G"))
            {
                game_id_min = command.GetTypedArgumentByName<CommandArgument_Int32>("G").ArgumentValue;
                game_id_max = game_id_min;
            }
            else
            {
                _logger.WriteLine("DungeonValidator: No game id given, evaluating all possible game ids");
            }

            if (game_id_min == game_id_max && command.HasArgumentWithName("D"))
            {
                dumpGeometryPath = command.GetTypedArgumentByName<CommandArgument_String>("D").ArgumentValue;
            }

            _logger.WriteLine("Validating layouts for game_ids {0} to {1}", game_id_min, game_id_max);

            // Get the room templates from the DB
            if (success && !roomTemplateSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the room templates from the DB: {0}", result));
                success = false;
            }

            // Get the mob type set from the DB
            if (success && !mobTypeSet.Initialize(connection_string, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob types from the DB: {0}", result));
                success = false;
            }

            // Get the mob spawn templates from the DB
            if (success && !mobSpawnTableSet.Initialize(connection_string, mobTypeSet, out result))
            {
                _logger.WriteLine(string.Format("DungeonValidator: Failed to load the mob spawn tables from the DB: {0}", result));
                success = false;
            }

            if (success)
            {
                DateTime startTime = DateTime.Now;

                // Test all possible world size configurations for each desired game id
                WorldTemplate[] worldTemplates = new WorldTemplate[] {
                    new WorldTemplate(GameConstants.eDungeonSize.small, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.medium, GameConstants.eDungeonDifficulty.normal),
                    new WorldTemplate(GameConstants.eDungeonSize.large, GameConstants.eDungeonDifficulty.normal),
                };

                for (int game_id = game_id_min; success && game_id <= game_id_max; ++game_id)
                {
                    foreach (WorldTemplate worldTemplate in worldTemplates)
                    {
                        DungeonLayout layout = new DungeonLayout(game_id, worldTemplate, roomTemplateSet, mobSpawnTableSet);

                        // Create the initial set of rooms for the world
                        if (!layout.BuildRoomLayout(out result))
                        {
                            _logger.WriteLine(
                                string.Format("DungeonValidator: Failed to generate dungeon layout, game_id:{0}, size:{1}",
                                game_id, worldTemplate.dungeon_size));
                            _logger.WriteLine(result);
                            success = false;
                        }

                        // Verify that this is a valid dungeon
                        if (success)
                        {
                            Dictionary<int, Portal> portalIdToPortalMap = BuildPortalIdMap(layout);

                            // Verify that all portals are connected correctly
                            success &= VerifyRoomPortals(layout, portalIdToPortalMap);

                            // Verify that every room is accessible to every other room
                            success &= VerifyRoomAccessibility(layout, portalIdToPortalMap);

                            // Verify monster spawners
                            success &= VerifyMobSpawners(layout);
                        }

                        // Dump the generated layout to a .obj file
                        if (dumpGeometryPath.Length > 0)
                        {
                            DumpLayoutGeometry(dumpGeometryPath, layout);
                        }
                    }

                    if (game_id_max > game_id_min)
                    {
                        if ((game_id % 1000) == 0)
                        {
                            TimeSpan elapsed = DateTime.Now.Subtract(startTime);

                            int percent_complete = 100 * (game_id - game_id_min) / (game_id_max - game_id_min);

                            _logger.Write("\r[{0:c}] {1}/{2} {3}%",
                                elapsed,
                                game_id-game_id_min,
                                game_id_max-game_id_min,
                                percent_complete);
                        }
                    }
                }

                // Write out a new line after the timing info
                _logger.WriteLine();
            }

            return success;
        }
예제 #4
0
 public WorldBuilder()
 {
     m_roomTemplateSet = new RoomTemplateSet();
     m_mobTypeSet = new MobTypeSet();
     m_mobSpawnTableSet = new MobSpawnTableSet();
 }
예제 #5
0
        private bool ValidateRoomTemplate(
            string templateName,
            RoomTemplate roomTemplate,
            MobSpawnTableSet mobSpawnTableSet,
            byte[] compressedNavCells,
            byte[] compressedPVS)
        {
            bool success= true;

            // Room has at least one teleporter
            success &= ValidateTeleportersAvailable(roomTemplate);

            // Door portals can only be on the following sides (+x, -x, +y, -y)
            // Stair portals can only be on the following sides (+z, -z)
            // Teleporter portals must have room side of none
            success &= ValidatePortalTypeExpectedRoomSide(roomTemplate);

            // Room doesn't have multiple doors or stairs per side
            success &= ValidateOnlyOneDoorPerSide(roomTemplate);

            // Room has nav mesh
            // All doors, stairs, and teleporters are on the nav mesh
            // All doors, stairs, and teleporters are accessible to each other on the nav mesh
            success &= ValidatePortalAccessibility(roomTemplate);

            // Mob spawner templates are valid
            // All mob spawner templates have spawn table
            // All mob spawner templates are on the nav mesh
            success &= ValidateMobSpawnerTemplates(roomTemplate, mobSpawnTableSet);

            // Energy Tank templates are valid
            // All energy tank templates have positive energy
            // All energy templates are on the nav mesh
            success &= ValidateEnergyTankTemplates(roomTemplate);

            // Compressed navCells/PVS can be decompressed back into the same nav-mesh
            success &= ValidateCompressedNavMeshData(roomTemplate, compressedNavCells, compressedPVS);

            return success;
        }
예제 #6
0
        private bool ValidateMobSpawnerTemplates(
            RoomTemplate roomTemplate,
            MobSpawnTableSet mobSpawnTableSet)
        {
            bool success = true;

            foreach (MobSpawnerTemplate spawnerTemplate in roomTemplate.MobSpawnerTemplates)
            {
                if (mobSpawnTableSet.GetMobSpawnTableByName(spawnerTemplate.SpawnTableName) == null)
                {
                    _logger.LogError(
                        string.Format("RoomTemplateParser: Template {0} has a monster spawner with invalid spawn table={1}",
                        roomTemplate.TemplateName,
                        spawnerTemplate.SpawnTableName));
                    success = false;
                }

                if (!roomTemplate.NavMeshTemplate.ComputeNavRefAtPoint(spawnerTemplate.Position).IsValid)
                {
                    _logger.LogError(
                        string.Format("RoomTemplateParser: Template {0} has a monster spawner off the nav mesh",
                        roomTemplate.TemplateName));
                    success = false;
                }
            }

            return success;
        }
예제 #7
0
        public void ParseRoomTemplates(
            AsyncRPGDataContext db_context,
            string template_path)
        {
            MobTypeSet mobTypeSet = new MobTypeSet();
            MobSpawnTableSet mobSpawnTableSet = new MobSpawnTableSet();

            // Clear out any existing room templates
            db_context.ExecuteCommand("DELETE FROM room_templates");

            // Get the mob type set from the DB
            mobTypeSet.Initialize(db_context);

            // Get the mob spawn templates from the DB
            mobSpawnTableSet.Initialize(db_context, mobTypeSet);

            // Read in each XML file and save it into the room templates table
            string[] templateFiles = Directory.GetFiles(template_path, "*.oel");

            if (templateFiles == null || templateFiles.Length == 0)
            {
                throw new Exception("RoomTemplateParser: No room template files (*.oel) found in directory: " + template_path);
            }

            {
                Dictionary<TypedFlags<MathConstants.eSignedDirection>, int> portalLayoutCounts =
                    new Dictionary<TypedFlags<MathConstants.eSignedDirection>, int>();
                bool anyRoomParsingErrors = false;

                foreach (string templateFile in templateFiles)
                {
                    string templateName = Path.GetFileNameWithoutExtension(templateFile);

                    RoomTemplate roomTemplate = null;
                    byte[] compressedNavCells = null;
                    byte[] compressedPVS = null;

                    // Parse the XML template from the file
                    XmlDocument doc = new XmlDocument();
                    doc.Load(templateFile);

                    // Parse the room template xml into a room template object
                    roomTemplate = new RoomTemplate(templateName, doc);

                    // Keep track of all of the unique portal layouts we encounter
                    if (portalLayoutCounts.ContainsKey(roomTemplate.PortalRoomSideBitmask))
                    {
                        portalLayoutCounts[roomTemplate.PortalRoomSideBitmask] += 1;
                    }
                    else
                    {
                        portalLayoutCounts.Add(roomTemplate.PortalRoomSideBitmask, 1);
                    }

                    // Extract the nav-mesh and visibility data in compressed form to save into the DB
                    roomTemplate.NavMeshTemplate.ToCompressedData(out compressedNavCells, out compressedPVS);

                    // Remove everything from the template XML that we wont care about at runtime
                    RemoveXmlNodeByXPath(doc, "/level/Floor");
                    RemoveXmlNodeByXPath(doc, "/level/Walls");
                    RemoveXmlNodeByXPath(doc, "/level/BackgroundObjects");
                    RemoveXmlNodeByXPath(doc, "/level/ForegroundObjects");
                    RemoveXmlNodeByXPath(doc, "/level/NavMesh");

                    if (ValidateRoomTemplate(
                            templateName,
                            roomTemplate,
                            mobSpawnTableSet,
                            compressedNavCells,
                            compressedPVS))
                    {
                        // Save the XML back into string
                        StringWriter stringWriter = new StringWriter();
                        XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
                        doc.WriteTo(xmlWriter);

                        RoomTemplates dbRoomTemplate =
                            new RoomTemplates
                            {
                                Name = templateName,
                                XML = stringWriter.ToString(),
                                CompressedNavMesh = compressedNavCells,
                                CompressedVisibility = compressedPVS
                            };

                        db_context.RoomTemplates.InsertOnSubmit(dbRoomTemplate);
                        db_context.SubmitChanges();

                        _logger.LogInfo("RoomTemplateParser: Added Room Template:");
                        _logger.LogInfo(templateFile);
                    }
                    else
                    {
                        anyRoomParsingErrors = true;
                    }
                }

                // Verify all possible door-side combinations are represented in the template file set
                if (portalLayoutCounts.Keys.Count < k_expectedRoomLayouts.Length)
                {
                    foreach (TypedFlags<MathConstants.eSignedDirection> expectedLayout in k_expectedRoomLayouts)
                    {
                        if (!portalLayoutCounts.ContainsKey(expectedLayout))
                        {
                            _logger.LogError(
                                string.Format(
                                "RoomTemplateParser: Missing expected room layout: {0}{1}{2}{3}{4}{5}",
                                expectedLayout.Test(MathConstants.eSignedDirection.positive_x) ? "X+" : "",
                                expectedLayout.Test(MathConstants.eSignedDirection.negative_x) ? "X-" : "",
                                expectedLayout.Test(MathConstants.eSignedDirection.positive_y) ? "Y+" : "",
                                expectedLayout.Test(MathConstants.eSignedDirection.negative_y) ? "Y-" : "",
                                expectedLayout.Test(MathConstants.eSignedDirection.positive_z) ? "Z+" : "",
                                expectedLayout.Test(MathConstants.eSignedDirection.negative_z) ? "Z-" : ""));

                            anyRoomParsingErrors = true;
                        }
                    }
                }

                if (anyRoomParsingErrors)
                {
                    throw new Exception("RoomTemplateParser: Failed to parse all room templates");
                }
            }
        }
예제 #8
0
        public static MobSpawner CreateMobSpawner(RoomKey roomKey, MobSpawnerTemplate template, MobSpawnTableSet spawnTableSet, Random rng)
        {
            MobSpawner newMobSpawner = new MobSpawner();

            newMobSpawner.m_room_key              = new RoomKey(roomKey);
            newMobSpawner.m_mob_spawner_id        = -1; // spawner ID not set until this gets saved into the DB
            newMobSpawner.m_position              = new Point3d(template.Position);
            newMobSpawner.m_remaining_spawn_count = RNGUtilities.RandomInt(rng, 0, template.MaxSpawnCount);
            newMobSpawner.m_random_seed           = rng.Next();
            newMobSpawner.m_spawn_table           = spawnTableSet.GetMobSpawnTableByName(template.SpawnTableName);

            return(newMobSpawner);
        }
예제 #9
0
        public static MobSpawner CreateMobSpawner(MobSpawners dbMobSpawner, MobSpawnTableSet spawnTableSet)
        {
            MobSpawner newMobSpawner = new MobSpawner();

            newMobSpawner.m_room_key = new RoomKey(dbMobSpawner.GameID, dbMobSpawner.RoomX, dbMobSpawner.RoomY, dbMobSpawner.RoomZ);
            newMobSpawner.m_mob_spawner_id = dbMobSpawner.MobSpawnerID;
            newMobSpawner.m_position = new Point3d((float)dbMobSpawner.X, (float)dbMobSpawner.Y, (float)dbMobSpawner.Z);
            newMobSpawner.m_remaining_spawn_count = dbMobSpawner.RemainingSpawnCount;
            newMobSpawner.m_random_seed = dbMobSpawner.RandomSeed;
            newMobSpawner.m_spawn_table = spawnTableSet.GetMobSpawnTableByID(dbMobSpawner.MobSpawnerTableID);

            return newMobSpawner;
        }