示例#1
0
        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);
        }