public new BlockSchematicStructure Clone() { BlockSchematicStructure cloned = new BlockSchematicStructure(); cloned.SizeX = SizeX; cloned.SizeY = SizeY; cloned.SizeZ = SizeZ; cloned.BlockCodes = new Dictionary <int, AssetLocation>(BlockCodes); cloned.ItemCodes = new Dictionary <int, AssetLocation>(ItemCodes); cloned.Indices = new List <uint>(Indices); cloned.BlockIds = new List <int>(BlockIds); cloned.BlockEntities = new Dictionary <uint, string>(BlockEntities); cloned.ReplaceMode = ReplaceMode; return(cloned); }
internal bool TryGenerateUnderground(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos) { int num = rand.Next(schematicDatas.Length); BlockSchematicStructure[] schematicStruc = schematicDatas[num]; BlockPos targetPos = pos.Copy(); if (schematicStruc[0].PathwayStarts.Length > 0) { // 1. Give up if non air block or mapheight is not at least 4 blocks higher // 2. Search up to 4 blocks downwards. Give up if no stone is found. // 3. Select one pathway randomly // 4. For every horizontal orientation // - Get the correctly rotated version for this pathway // - Starting at 2 blocks away, move one block closer each iteration // - Check if // - at every pathway block pos there is stone or air // - at least one pathway block has an air block facing towards center? // - If yes, remove the blocks that are in the way and place schematic Block block = blockAccessor.GetBlock(targetPos); if (block.Id != 0) { return(false); } // 1./2. Search an underground position that has air and a stone floor below bool found = false; for (int dy = 0; dy <= 4; dy++) { targetPos.Down(); block = blockAccessor.GetBlock(targetPos); if (block.BlockMaterial == EnumBlockMaterial.Stone) { targetPos.Up(); found = true; break; } } if (!found) { return(false); } // 3. Random pathway found = false; int pathwayNum = rand.Next(schematicStruc[0].PathwayStarts.Length); int targetOrientation = 0; int targetDistance = -1; BlockFacing targetFacing = null; BlockPos[] pathway = null; // 4. At that position search for a suitable stone wall in any direction for (targetOrientation = 0; targetOrientation < 4; targetOrientation++) { // Try every rotation pathway = schematicStruc[targetOrientation].PathwayOffsets[pathwayNum]; // This is the facing we are currently checking targetFacing = schematicStruc[targetOrientation].PathwaySides[pathwayNum]; targetDistance = CanPlacePathwayAt(blockAccessor, pathway, targetFacing, targetPos); if (targetDistance != -1) { break; } } if (targetDistance == -1) { return(false); } BlockPos pathwayStart = schematicStruc[targetOrientation].PathwayStarts[pathwayNum]; // Move back the structure so that the door aligns to the cave wall targetPos.Add( -pathwayStart.X - targetFacing.Normali.X * targetDistance, -pathwayStart.Y - targetFacing.Normali.Y * targetDistance, -pathwayStart.Z - targetFacing.Normali.Z * targetDistance ); if (!TestUndergroundCheckPositions(blockAccessor, targetPos, schematicStruc[targetOrientation].UndergroundCheckPositions)) { return(false); } schematicStruc[targetOrientation].Place(blockAccessor, worldForCollectibleResolve, targetPos); // Free up a layer of blocks in front of the door ushort blockId = 0; // blockAccessor.GetBlock(new AssetLocation("creativeblock-37")).BlockId; for (int i = 0; i < pathway.Length; i++) { for (int d = 0; d <= targetDistance; d++) { tmpPos.Set( targetPos.X + pathwayStart.X + pathway[i].X + (d + 1) * targetFacing.Normali.X, targetPos.Y + pathwayStart.Y + pathway[i].Y + (d + 1) * targetFacing.Normali.Y, targetPos.Z + pathwayStart.Z + pathway[i].Z + (d + 1) * targetFacing.Normali.Z ); blockAccessor.SetBlock(blockId, tmpPos); } } return(true); } BlockSchematicStructure schematic = schematicStruc[rand.Next(4)]; if (!TestUndergroundCheckPositions(blockAccessor, targetPos, schematic.UndergroundCheckPositions)) { return(false); } schematic.Place(blockAccessor, worldForCollectibleResolve, targetPos); //Console.WriteLine("/tp ={0} ={1} ={2} ({3} - {4})", targetPos.X, targetPos.Y, targetPos.Z, Code, Schematics[num]); return(false); }
public void Init(ICoreServerAPI api, BlockLayerConfig config) { rand = api.World.Rand; List <BlockSchematicStructure[]> schematics = new List <BlockSchematicStructure[]>(); for (int i = 0; i < Schematics.Length; i++) { string error = ""; IAsset[] assets; if (Schematics[i].EndsWith("*")) { assets = api.Assets.GetMany("worldgen/schematics/" + Schematics[i].Substring(0, Schematics[i].Length - 1)).ToArray(); } else { assets = new IAsset[] { api.Assets.Get("worldgen/schematics/" + Schematics[i] + ".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; } 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].LoadMetaInformation(api.World.BlockAccessor); } schematics.Add(rotations); } } this.schematicDatas = schematics.ToArray(); if (ReplaceWithBlocklayers != null) { replaceblockids = new ushort[ReplaceWithBlocklayers.Length]; for (int i = 0; i < replaceblockids.Length; i++) { replaceblockids[i] = (ushort)api.World.GetBlock(ReplaceWithBlocklayers[i]).Id; } } }
internal bool TryGenerateAtSurface(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.Next(schematicDatas.Length); int orient = rand.Next(4); BlockSchematicStructure schematic = schematicDatas[num][orient]; int widthHalf = (int)Math.Ceiling(schematic.SizeX / 2f); int lengthHalf = (int)Math.Ceiling(schematic.SizeZ / 2f); // Ensure not submerged in water tmpPos.Set(pos.X - widthHalf, pos.Y + OffsetY, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(false); } tmpPos.Set(pos.X + widthHalf, pos.Y + OffsetY, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(false); } tmpPos.Set(pos.X - widthHalf, pos.Y + OffsetY, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(false); } tmpPos.Set(pos.X + widthHalf, pos.Y + OffsetY, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(false); } // Probe all 4 corners + center if they either touch the surface or are sightly below ground int centerDiff = blockAccessor.GetTerrainMapheightAt(pos) - pos.Y; tmpPos.Set(pos.X - widthHalf, 0, pos.Z - lengthHalf); int topLeftDiff = blockAccessor.GetTerrainMapheightAt(tmpPos) - pos.Y; tmpPos.Set(pos.X + widthHalf, 0, pos.Z - lengthHalf); int topRightDiff = blockAccessor.GetTerrainMapheightAt(tmpPos) - pos.Y; tmpPos.Set(pos.X - widthHalf, 0, pos.Z + lengthHalf); int botLeftDiff = blockAccessor.GetTerrainMapheightAt(tmpPos) - pos.Y; tmpPos.Set(pos.X + widthHalf, 0, pos.Z + lengthHalf); int botRightDiff = blockAccessor.GetTerrainMapheightAt(tmpPos) - pos.Y; bool ok = centerDiff >= -3 && centerDiff <= 1 && topLeftDiff >= -3 && topLeftDiff <= 1 && topRightDiff >= -3 && topRightDiff <= 1 && botLeftDiff >= -3 && botLeftDiff <= 1 && botRightDiff >= -3 && botRightDiff <= 1 ; if (ok) { schematic.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids); } return(ok); }