protected BlockSchematicStructure GetGeneratableStructure(VillageSchematic schem, IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos) { int chunksize = blockAccessor.ChunkSize; int climate = GameMath.BiLerpRgbColor((float)(pos.X % chunksize) / chunksize, (float)(pos.Z % chunksize) / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); int num = rand.NextInt(schem.Structures.Length); BlockSchematicStructure schematic = schem.Structures[num]; int widthHalf = (int)Math.Ceiling(schematic.SizeX / 2f); int lengthHalf = (int)Math.Ceiling(schematic.SizeZ / 2f); pos.Y += schem.OffsetY; // Probe all 4 corners + center if they are on the same height int centerY = blockAccessor.GetTerrainMapheightAt(pos); tmpPos.Set(pos.X - widthHalf, 0, pos.Z - lengthHalf); int topLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X + widthHalf, 0, pos.Z - lengthHalf); int topRightY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X - widthHalf, 0, pos.Z + lengthHalf); int botLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X + widthHalf, 0, pos.Z + lengthHalf); int botRightY = blockAccessor.GetTerrainMapheightAt(tmpPos); int diff = GameMath.Max(centerY, topLeftY, topRightY, botLeftY, botRightY) - GameMath.Min(centerY, topLeftY, topRightY, botLeftY, botRightY); if (diff > 2) { return(null); } pos.Y += centerY - pos.Y + 1 + schem.OffsetY; if (pos.Y <= 0) { return(null); } // Ensure not floating on water tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } // Ensure not submerged in water tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } if (!TestUndergroundCheckPositions(blockAccessor, pos, schematic.UndergroundCheckPositions)) { return(null); } if (isStructureAt(pos, worldForCollectibleResolve)) { return(null); } return(schematic); }
public void Init(ICoreServerAPI api, BlockLayerConfig config, LCGRandom rand) { this.rand = rand; totalWeight = 0; for (int i = 0; i < Schematics.Length; i++) { List <BlockSchematicStructure> schematics = new List <BlockSchematicStructure>(); string error = ""; IAsset[] assets; VillageSchematic schem = Schematics[i]; totalWeight += schem.Weight; if (schem.Path.EndsWith("*")) { assets = api.Assets.GetMany("worldgen/schematics/" + schem.Path.Substring(0, schem.Path.Length - 1)).ToArray(); } else { assets = new IAsset[] { api.Assets.Get("worldgen/schematics/" + Schematics[i].Path + ".json") }; } for (int j = 0; j < assets.Length; j++) { IAsset asset = assets[j]; BlockSchematicStructure schematic = asset.ToObject <BlockSchematicStructure>(); if (schematic == null) { api.World.Logger.Warning("Could not load {0}: {1}", Schematics[i], error); continue; } schematic.FromFileName = asset.Name; BlockSchematicStructure[] rotations = new BlockSchematicStructure[4]; rotations[0] = schematic; for (int k = 0; k < 4; k++) { if (k > 0) { rotations[k] = rotations[0].Clone(); rotations[k].TransformWhilePacked(api.World, EnumOrigin.BottomCenter, k * 90); } rotations[k].blockLayerConfig = config; rotations[k].Init(api.World.BlockAccessor); rotations[k].LoadMetaInformationAndValidate(api.World.BlockAccessor, api.World, schematic.FromFileName); } schematics.AddRange(rotations); } schem.Structures = schematics.ToArray(); } if (ReplaceWithBlocklayers != null) { replaceblockids = new int[ReplaceWithBlocklayers.Length]; for (int i = 0; i < replaceblockids.Length; i++) { Block block = api.World.GetBlock(ReplaceWithBlocklayers[i]); if (block == null) { throw new Exception(string.Format("Schematic with code {0} has replace block layer {1} defined, but no such block found!", Code, ReplaceWithBlocklayers[i])); } else { replaceblockids[i] = (ushort)block.Id; } } } }
public bool TryGenerate(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, DidGenerate didGenerateStructure) { this.climateUpLeft = climateUpLeft; this.climateUpRight = climateUpRight; this.climateBotLeft = climateBotLeft; this.climateBotRight = climateBotRight; float cnt = QuantityStructures.nextFloat(); int minQuantity = (int)cnt; BlockPos schemPos = pos.Copy(); Cuboidi location = new Cuboidi(); rand.InitPositionSeed(pos.X, pos.Z); List <GeneratableStructure> generatables = new List <GeneratableStructure>(); while (cnt-- > 0) { if (cnt < 1 && rand.NextDouble() > cnt) { break; } int tries = 30; while (tries-- > 0) { schemPos.Set(pos); schemPos.Add(rand.NextInt(50) - 25, 0, rand.NextInt(50) - 25); schemPos.Y = blockAccessor.GetTerrainMapheightAt(schemPos); double rndVal = rand.NextDouble() * totalWeight; int i = 0; VillageSchematic schem = null; while (rndVal > 0) { schem = Schematics[i++]; rndVal -= schem.Weight; } BlockSchematicStructure struc = GetGeneratableStructure(schem, blockAccessor, worldForCollectibleResolve, schemPos); if (struc != null) { location.Set(schemPos.X, schemPos.Y, schemPos.Z, schemPos.X + struc.SizeX, schemPos.Y + struc.SizeY, schemPos.Z + struc.SizeZ); bool intersect = false; for (int k = 0; k < generatables.Count; k++) { if (location.IntersectsOrTouches(generatables[k].location)) { intersect = true; break; } } if (!intersect) { generatables.Add(new GeneratableStructure() { struc = struc, pos = schemPos.Copy(), location = location.Clone() }); } break; } } } if (generatables.Count >= minQuantity) { foreach (var val in generatables) { val.struc.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, val.pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids); didGenerateStructure(val.location, val.struc); } } return(true); }