public void GetByID_OneItem_ReturnsAreaWalkmesh() { // Arrange var id = Guid.NewGuid(); AreaWalkmesh entity = new AreaWalkmesh { ID = id }; // Act MessageHub.Instance.Publish(new OnCacheObjectSet <AreaWalkmesh>(entity)); // Assert Assert.AreNotSame(entity, _cache.GetByID(id)); }
// Area baking process // Run through and look for valid locations for later use by the spawn system. // Each tile is 10x10 meters. The "step" value in the config table determines how many meters we progress before checking for a valid location. private static void BakeArea(NWArea area) { _walkmeshesByArea[area] = new List <AreaWalkmesh>(); const float MinDistance = 6.0f; var dbArea = DataService.Area.GetByResref(area.Resref); int arraySizeX = dbArea.Width * (10 / AreaBakeStep); int arraySizeY = dbArea.Height * (10 / AreaBakeStep); for (int x = 0; x < arraySizeX; x++) { for (int y = 0; y < arraySizeY; y++) { Location checkLocation = _.Location(area.Object, _.Vector3(x * AreaBakeStep, y * AreaBakeStep), 0.0f); int material = _.GetSurfaceMaterial(checkLocation); bool isWalkable = Convert.ToInt32(_.Get2DAString("surfacemat", "Walk", material)) == 1; // Location is not walkable if another object exists nearby. NWObject nearest = (_.GetNearestObjectToLocation(checkLocation, ObjectType.Creature | ObjectType.Door | ObjectType.Placeable | ObjectType.Trigger)); float distance = _.GetDistanceBetweenLocations(checkLocation, nearest.Location); if (nearest.IsValid && distance <= MinDistance) { isWalkable = false; } if (isWalkable) { AreaWalkmesh mesh = new AreaWalkmesh() { AreaID = dbArea.ID, LocationX = x * AreaBakeStep, LocationY = y * AreaBakeStep, LocationZ = _.GetGroundHeight(checkLocation) }; _walkmeshesByArea[area].Add(mesh); } } } Console.WriteLine("Area walkmesh up to date: " + area.Name); }
public void GetByID_TwoItems_ReturnsCorrectObject() { // Arrange var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); AreaWalkmesh entity1 = new AreaWalkmesh { ID = id1 }; AreaWalkmesh entity2 = new AreaWalkmesh { ID = id2 }; // Act MessageHub.Instance.Publish(new OnCacheObjectSet <AreaWalkmesh>(entity1)); MessageHub.Instance.Publish(new OnCacheObjectSet <AreaWalkmesh>(entity2)); // Assert Assert.AreNotSame(entity1, _cache.GetByID(id1)); Assert.AreNotSame(entity2, _cache.GetByID(id2)); }
public void GetByID_RemovedItem_ReturnsCorrectObject() { // Arrange var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); AreaWalkmesh entity1 = new AreaWalkmesh { ID = id1 }; AreaWalkmesh entity2 = new AreaWalkmesh { ID = id2 }; // Act MessageHub.Instance.Publish(new OnCacheObjectSet <AreaWalkmesh>(entity1)); MessageHub.Instance.Publish(new OnCacheObjectSet <AreaWalkmesh>(entity2)); MessageHub.Instance.Publish(new OnCacheObjectDeleted <AreaWalkmesh>(entity1)); // Assert Assert.Throws <KeyNotFoundException>(() => { _cache.GetByID(id1); }); Assert.AreNotSame(entity2, _cache.GetByID(id2)); }
// Area baking process // Check if walkmesh matches what's in the database. // If it doesn't, run through and look for valid locations for later use by the spawn system. // Each tile is 10x10 meters. The "step" value in the config table determines how many meters we progress before checking for a valid location. // If you adjust this to get finer precision your database may explode with a ton of records. I chose a value that got me the // accuracy I wanted, without too much overhead. Your mileage may vary. private void BakeAreas() { var config = _data.GetAll <ServerConfiguration>().First(); int Step = config.AreaBakeStep; const float MinDistance = 6.0f; foreach (var area in NWModule.Get().Areas) { var dbArea = _data.Single <Area>(x => x.Resref == area.Resref); int arraySizeX = dbArea.Width * (10 / Step); int arraySizeY = dbArea.Height * (10 / Step); Tuple <bool, float>[,] locations = new Tuple <bool, float> [arraySizeX, arraySizeY]; string walkmesh = string.Empty; for (int x = 0; x < arraySizeX; x++) { for (int y = 0; y < arraySizeY; y++) { Location checkLocation = _.Location(area.Object, _.Vector(x * Step, y * Step), 0.0f); int material = _.GetSurfaceMaterial(checkLocation); bool isWalkable = Convert.ToInt32(_.Get2DAString("surfacemat", "Walk", material)) == 1; // Location is not walkable if another object exists nearby. NWObject nearest = (_.GetNearestObjectToLocation(OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_TRIGGER, checkLocation)); float distance = _.GetDistanceBetweenLocations(checkLocation, nearest.Location); if (nearest.IsValid && distance <= MinDistance) { isWalkable = false; } locations[x, y] = new Tuple <bool, float>(isWalkable, _.GetGroundHeight(checkLocation)); walkmesh += isWalkable ? "1" : "0"; } } if (dbArea.Walkmesh != walkmesh) { dbArea.Walkmesh = walkmesh; dbArea.DateLastBaked = DateTime.UtcNow; _data.SubmitDataChange(dbArea, DatabaseActionType.Update); Console.WriteLine("Baking area because its walkmesh has changed since last run: " + area.Name); var walkmeshes = _data.Where <AreaWalkmesh>(x => x.AreaID == dbArea.ID).ToList(); for (int x = walkmeshes.Count - 1; x >= 0; x--) { var mesh = walkmeshes.ElementAt(x); _data.SubmitDataChange(mesh, DatabaseActionType.Delete); } Console.WriteLine("Cleared old walkmesh. Adding new one now."); int records = 0; for (int x = 0; x < arraySizeX; x++) { for (int y = 0; y < arraySizeY; y++) { // Ignore any points in the area that aren't walkable. bool isWalkable = locations[x, y].Item1; if (!isWalkable) { continue; } float z = locations[x, y].Item2; AreaWalkmesh mesh = new AreaWalkmesh() { AreaID = dbArea.ID, LocationX = x * Step, LocationY = y * Step, LocationZ = z }; _data.SubmitDataChange(mesh, DatabaseActionType.Insert); records++; } } Console.WriteLine("Saved " + records + " records."); } Console.WriteLine("Area walkmesh up to date: " + area.Name); } }