private bool ValidateTeleportersAvailable(
            RoomTemplate roomTemplate)
        {
            bool success = true;

            if (roomTemplate.PortalTemplates.Select(p => p.PortalType == ePortalType.teleporter).Count() == 0)
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} does not contain any teleporters",
                    roomTemplate.TemplateName));
                success = false;
            }

            return success;
        }
        private bool ValidatePortalTypeExpectedRoomSide(
            RoomTemplate roomTemplate)
        {
            bool success = true;

            foreach (PortalTemplate portalTempate in roomTemplate.PortalTemplates)
            {
                int portal_id = portalTempate.PortalID;
                MathConstants.eSignedDirection roomSide = portalTempate.PortalRoomSide;

                switch (portalTempate.PortalType)
                {
                    case ePortalType.door:
                        if (roomSide != MathConstants.eSignedDirection.positive_x && roomSide != MathConstants.eSignedDirection.negative_x &&
                            roomSide != MathConstants.eSignedDirection.positive_y && roomSide != MathConstants.eSignedDirection.negative_y)
                        {
                            _logger.LogError(
                                string.Format(
                                "RoomTemplateParser: Template {0}, door portal id={1} on unexpected side={2}",
                                roomTemplate.TemplateName, portal_id, roomSide));
                            success = false;
                        }
                        break;
                    case ePortalType.stairs:
                        if (roomSide != MathConstants.eSignedDirection.positive_z && roomSide != MathConstants.eSignedDirection.negative_z)
                        {
                            _logger.LogError(
                                string.Format(
                                "RoomTemplateParser: Template {0}, stairs portal id={1} on unexpected side={2}",
                                roomTemplate.TemplateName, portal_id, roomSide));
                            success = false;
                        }
                        break;
                    case ePortalType.teleporter:
                        if (roomSide != MathConstants.eSignedDirection.none)
                        {
                            _logger.LogError(
                                string.Format(
                                "RoomTemplateParser: Template {0}, teleporter portal id={1} on unexpected side={2}",
                                roomTemplate.TemplateName, portal_id, roomSide));
                            success = false;
                        }
                        break;
                }
            }

            return success;
        }
        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;
        }
        private bool ValidateOnlyOneDoorPerSide(
            RoomTemplate roomTemplate)
        {
            bool success = true;

            if (roomTemplate.PortalTemplates
                    .Select(p => p.PortalType == ePortalType.door && p.PortalRoomSide == MathConstants.eSignedDirection.negative_x)
                    .Count() <= 1)
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} contains more than one door on the -X side",
                    roomTemplate.TemplateName));
                success = false;
            }

            if (roomTemplate.PortalTemplates
                    .Select(p => p.PortalType == ePortalType.door && p.PortalRoomSide == MathConstants.eSignedDirection.positive_x)
                    .Count() <= 1)
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} contains more than one door on the +X side",
                    roomTemplate.TemplateName));
                success = false;
            }

            if (roomTemplate.PortalTemplates
                    .Select(p => p.PortalType == ePortalType.door && p.PortalRoomSide == MathConstants.eSignedDirection.negative_y)
                    .Count() <= 1)
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} contains more than one door on the -Y side",
                    roomTemplate.TemplateName));
                success = false;
            }

            if (roomTemplate.PortalTemplates
                    .Select(p => p.PortalType == ePortalType.door && p.PortalRoomSide == MathConstants.eSignedDirection.positive_y)
                    .Count() <= 1)
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} contains more than one door on the +Y side",
                    roomTemplate.TemplateName));
                success = false;
            }

            return success;
        }
        private bool ValidatePortalAccessibility(
            RoomTemplate roomTemplate)
        {
            bool success = true;

            // Room has nav mesh
            if (!roomTemplate.NavMeshTemplate.IsNavCellDataEmpty)
            {
                int sharedPortalConnectivityId = NavMesh.EMPTY_NAV_CELL;

                // All doors, stairs, and teleporters are on the nav mesh
                // All doors, stairs, and teleporters are accessible to each other on the nav mesh
                foreach (PortalTemplate portalTemplate in roomTemplate.PortalTemplates)
                {
                    Point3d portalCenter= portalTemplate.BoundingBox.Center;
                    NavRef portalNavRef= roomTemplate.NavMeshTemplate.ComputeNavRefAtPoint(portalCenter);
                    int portalConnectivityId = roomTemplate.NavMeshTemplate.GetNavRefConnectivityID(portalNavRef);

                    if (portalConnectivityId != NavMesh.EMPTY_NAV_CELL)
                    {
                        if (sharedPortalConnectivityId != NavMesh.EMPTY_NAV_CELL)
                        {
                            if (sharedPortalConnectivityId != portalConnectivityId)
                            {
                                _logger.LogError(
                                    string.Format(
                                    "RoomTemplateParser: Template {0}, portal id={1} is not connected to all other portals on the nav mesh",
                                    roomTemplate.TemplateName, portalTemplate.PortalID));
                                success = false;
                            }
                        }
                        else
                        {
                            sharedPortalConnectivityId = portalConnectivityId;
                        }
                    }
                    else
                    {
                        _logger.LogError(
                            string.Format(
                            "RoomTemplateParser: Template {0}, portal id={1} has center not on the nav mesh",
                            roomTemplate.TemplateName, portalTemplate.PortalID));
                        success = false;
                    }
                }
            }
            else
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} missing a nav mesh",
                    roomTemplate.TemplateName));
                success = false;
            }

            return success;
        }
        private bool ValidateEnergyTankTemplates(
            RoomTemplate roomTemplate)
        {
            bool success = true;

            foreach (EnergyTankTemplate energyTankTemplate in roomTemplate.EnergyTankTemplates)
            {
                if (energyTankTemplate.Energy < 0)
                {
                    _logger.LogError(
                        string.Format("RoomTemplateParser: Template {0} has an energy tank with non-positive energy",
                        roomTemplate.TemplateName));
                    success = false;
                }

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

            return success;
        }
        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;
        }
        private bool ValidateCompressedNavMeshData(
            RoomTemplate roomTemplate,
            byte[] compressedNavCells,
            byte[] compressedPVS)
        {
            bool success = true;
            NavMesh testNavMesh = NavMesh.FromCompressedNavMeshData(compressedNavCells, compressedPVS);

            if (!testNavMesh.Equals(roomTemplate.NavMeshTemplate))
            {
                _logger.LogError(
                    string.Format("RoomTemplateParser: Template {0} nav mesh decompressed incorrectly",
                    roomTemplate.TemplateName));
                Debug.Assert(false, "Nav Mesh decompression error");
                success = false;
            }

            return success;
        }
        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");
                }
            }
        }
Esempio n. 10
0
        //TODO: LoadRoom - Convert this over to a request processor
        public static bool LoadRoom(
            AsyncRPGDataContext context,
            World world,
            RoomKey room_key,
            out Room room,
            out string result)
        {
            bool   success;
            string json_static_data = WorldQueries.GetRoomStaticData(context, room_key);

            room    = null;
            success = false;

            // Load static room data for this room
            if (json_static_data.Length > 0)
            {
                StaticRoomData static_room_data = null;

                try
                {
                    if (json_static_data.Length == 0)
                    {
                        throw new ArgumentException();
                    }

                    static_room_data = JsonMapper.ToObject <StaticRoomData>(json_static_data);
                }
                catch (System.Exception)
                {
                    static_room_data = null;
                }

                if (static_room_data != null)
                {
                    room = new Room(room_key);
                    room.static_room_data = static_room_data;

                    success = true;
                    result  = SuccessMessages.GENERAL_SUCCESS;
                }
                else
                {
                    result = ErrorMessages.DB_ERROR + "(Failed to parse room static data)";
                }
            }
            else
            {
                result = ErrorMessages.DB_ERROR + "(Failed to get room static data)";
            }

            // If the static room data parsed, load everything else
            if (success)
            {
                RoomTemplate roomTemplate = world.RoomTemplates.GetTemplateByName(room.static_room_data.room_template_name);

                // Load the random seed for the room
                room.random_seed = WorldQueries.GetRoomRandomSeed(context, room_key);

                // Setup the runtime nav mesh
                room.runtime_nav_mesh = new NavMesh(room.room_key, roomTemplate.NavMeshTemplate);

                // Load all of the portals for this room
                room.portals = WorldQueries.GetRoomPortals(context, room_key);

                // Flag all of the room sides that have portals
                foreach (Portal p in room.portals)
                {
                    room.portalRoomSideBitmask.Set(p.room_side, true);
                }

                // Load mob spawners for this room
                room.mobSpawners = MobQueries.GetMobSpawners(context, world.MobSpawnTables, room_key);
            }

            return(success);
        }
Esempio n. 11
0
        public static Dictionary<string, RoomTemplate> LoadRoomTemplates(
            AsyncRPGDataContext context)
        {
            Dictionary<string, RoomTemplate> roomTemplates = new Dictionary<string, RoomTemplate>();

            var templates = from t in context.RoomTemplates select t;

            foreach (RoomTemplates roomTemplateDBEntry in templates)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(roomTemplateDBEntry.XML);

                RoomTemplate roomTemplate =
                    new RoomTemplate(
                        roomTemplateDBEntry.Name,
                        xmlDoc,
                        roomTemplateDBEntry.CompressedNavMesh,
                        roomTemplateDBEntry.CompressedVisibility);

                roomTemplates[roomTemplateDBEntry.Name] = roomTemplate;
            }

            return roomTemplates;
        }
Esempio n. 12
0
        private bool CreateNormalPortals(out string result)
        {
            bool success = true;

            result = SuccessMessages.GENERAL_SUCCESS;

            // Create portals in each room
            for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                RoomIndex    roomIndex    = iterator.Current;
                RoomKey      roomKey      = GetRoomKeyForRoomIndex(roomIndex);
                RoomLayout   room         = GetRoomByIndex(roomIndex);
                RoomTemplate roomTemplate = m_roomTemplateSet.GetTemplateByName(room.static_room_data.room_template_name);

                foreach (PortalTemplate portalTemplate in roomTemplate.PortalTemplates)
                {
                    if (portalTemplate.PortalType != ePortalType.teleporter)
                    {
                        Portal portal = new Portal();

                        portal.bounding_box = portalTemplate.BoundingBox;
                        portal.room_side    = portalTemplate.PortalRoomSide;
                        portal.room_x       = roomKey.x;
                        portal.room_y       = roomKey.y;
                        portal.room_z       = roomKey.z;
                        portal.portal_type  = portalTemplate.PortalType;

                        // This is a temp ID for the purpose of portal connection.
                        // A new ID will get assigned when inserting this portal into the DB.
                        portal.portal_id = m_nextPortalId;
                        ++m_nextPortalId;

                        // This get sets in the next pass
                        portal.target_portal_id = -1;

                        room.portals.Add(portal);
                    }
                }
            }

            // Connect neighboring portals
            for (RoomIndexIterator iterator = new RoomIndexIterator(m_roomGrid);
                 success && iterator.Valid;
                 iterator.Next())
            {
                RoomIndex  roomIndex = iterator.Current;
                RoomLayout room      = GetRoomByIndex(roomIndex);

                foreach (Portal portal in room.portals)
                {
                    MathConstants.eSignedDirection opposingRoomSide = RoomKey.GetOpposingRoomSide(portal.room_side);
                    RoomIndex  opposingRoomIndex = roomIndex.GetOpposingRoomIndex(portal.room_side);
                    RoomLayout opposingRoom      = GetRoomByIndex(opposingRoomIndex);
                    Portal     opposingPortal    = opposingRoom.portals.Find(p => p.room_side == opposingRoomSide);

                    if (opposingPortal != null)
                    {
                        portal.target_portal_id         = opposingPortal.portal_id;
                        opposingPortal.target_portal_id = portal.portal_id;
                    }
                    else
                    {
                        result  = ErrorMessages.DUNGEON_LAYOUT_ERROR;
                        success = false;
                        break;
                    }
                }
            }

            return(success);
        }