public StructureBuildActiveActionExecuteBuilder(IFixture fixture) { this.fixture = fixture; requirementCsvFactory = fixture.Freeze <IRequirementCsvFactory>(); requirementCsvFactory .GetLayoutRequirement(Arg.Any <ushort>(), Arg.Any <byte>()) .Validate(Arg.Any <IStructure>(), Arg.Any <ushort>(), Arg.Any <uint>(), Arg.Any <uint>(), Arg.Any <byte>()) .Returns(true); structureBaseStats = fixture.Freeze <IStructureBaseStats>(); structureBaseStats.Size.Returns <byte>(0); var structureCost = new Resource(1234, 8446, 1343, 1234, 1246); structureBaseStats.Cost.Returns(structureCost); var structure = fixture.Freeze <IStructure>(); structure.Stats.Base.Returns(structureBaseStats); objectTypeFactory = fixture.Freeze <IObjectTypeFactory>(); objectTypeFactory.IsObjectType("NoRoadRequired", Arg.Any <ushort>()).Returns(true); city = fixture.Create <ICity>(); city.PrimaryPosition.Returns(new Position(99, 98)); city.Radius.Returns <byte>(5); city.Resource.HasEnough(structureBaseStats.Cost).Returns(true); city.CreateStructure(Arg.Any <ushort>(), Arg.Any <byte>(), Arg.Any <uint>(), Arg.Any <uint>()).Returns(structure); roadPathFinder = fixture.Freeze <IRoadPathFinder>(); roadPathFinder.CanBuild(Arg.Any <Position>(), Arg.Any <byte>(), city, Arg.Any <bool>()).Returns(Error.Ok); tileLocator = fixture.Freeze <ITileLocator>(); tileLocator.TileDistance(new Position(99, 98), 1, Arg.Any <Position>(), 1).Returns(1); world = fixture.Freeze <IWorld>(); ICity outCity; world.TryGetObjects(Arg.Any <uint>(), out outCity).Returns(x => { x[1] = city; return(true); }); world.Regions.GetObjectsInTile(Arg.Any <uint>(), Arg.Any <uint>()).Returns(new List <ISimpleGameObject>()); world.Regions.IsValidXandY(0, 0).ReturnsForAnyArgs(true); world.Regions.Add(structure).Returns(true); structureCsvFactory = fixture.Freeze <IStructureCsvFactory>(); structureCsvFactory.GetBaseStats(0, 0).ReturnsForAnyArgs(structureBaseStats); formula = Substitute.For <Formula>(); formula.CityMaxConcurrentBuildActions(0, 0, null, null).ReturnsForAnyArgs(Error.Ok); formula.StructureCost(null, null).ReturnsForAnyArgs(structureCost); fixture.Register(() => formula); }
public override Error Execute() { ICity city; if (!world.TryGetObjects(cityId, out city)) { return(Error.ObjectNotFound); } var maxConcurrentUpgradesResult = formula.CityMaxConcurrentBuildActions(type, ActionId, city, objectTypeFactory); if (maxConcurrentUpgradesResult != Error.Ok) { return(maxConcurrentUpgradesResult); } var structureBaseStats = structureCsvFactory.GetBaseStats(type, level); var lockedRegions = world.Regions.LockMultitileRegions(X, Y, structureBaseStats.Size); foreach (var position in tileLocator.ForeachMultitile(X, Y, structureBaseStats.Size)) { var tileType = world.Regions.GetTileType(position.X, position.Y); // tile requirement if (!string.IsNullOrEmpty(tileRequirement) && !objectTypeFactory.IsTileType(tileRequirement, tileType)) { world.Regions.UnlockRegions(lockedRegions); return(Error.TileMismatch); } // Only allow buildings that require resource tile to built on them if (tileRequirement != "TileResource" && objectTypeFactory.IsTileType("TileResource", tileType)) { world.Regions.UnlockRegions(lockedRegions); return(Error.TileMismatch); } // dont allow building on edge of world if (!world.Regions.IsValidXandY(position.X, position.Y)) { world.Regions.UnlockRegions(lockedRegions); return(Error.ActionInvalid); } // radius requirements if (tileLocator.TileDistance(city.PrimaryPosition, 1, position, 1) >= city.Radius) { world.Regions.UnlockRegions(lockedRegions); return(Error.NotWithinWalls); } // check if tile is occupied if (world.Regions.GetObjectsInTile(position.X, position.Y).Any(obj => obj is IStructure)) { world.Regions.UnlockRegions(lockedRegions); return(Error.StructureExists); } } // cost requirement cost = formula.StructureCost(city, structureBaseStats); if (!city.Resource.HasEnough(cost)) { world.Regions.UnlockRegions(lockedRegions); return(Error.ResourceNotEnough); } // layout requirement if (!requirementCsvFactory.GetLayoutRequirement(type, level).Validate(WorkerObject as IStructure, type, X, Y, structureBaseStats.Size)) { world.Regions.UnlockRegions(lockedRegions); return(Error.LayoutNotFullfilled); } // check for road requirements var requiresRoad = !objectTypeFactory.IsObjectType("NoRoadRequired", type); var canBuild = roadPathFinder.CanBuild(new Position(X, Y), structureBaseStats.Size, city, requiresRoad); if (canBuild != Error.Ok) { world.Regions.UnlockRegions(lockedRegions); return(canBuild); } // add structure to the map IStructure structure = city.CreateStructure(type, 0, X, Y); city.BeginUpdate(); city.Resource.Subtract(cost); city.EndUpdate(); structure.BeginUpdate(); if (!world.Regions.Add(structure)) { city.ScheduleRemove(structure, false); city.BeginUpdate(); city.Resource.Add(cost); city.EndUpdate(); structure.EndUpdate(); world.Regions.UnlockRegions(lockedRegions); return(Error.MapFull); } structure.EndUpdate(); callbackProcedure.OnStructureUpgrade(structure); structureId = structure.ObjectId; // add to queue for completion var buildTime = formula.BuildTime(structureBaseStats.BuildTime, city, city.Technologies); endTime = SystemClock.Now.AddSeconds(CalculateTime(buildTime)); BeginTime = SystemClock.Now; city.References.Add(structure, this); world.Regions.UnlockRegions(lockedRegions); return(Error.Ok); }