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"); } } }
//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); }
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; }
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); }