예제 #1
0
        internal Cuboidf[] GetSelectionBoxes(Vec3i forSize, EnumCircuitSelectionType selType, IPlayer forPlayer = null)
        {
            if (currentSelectionType == selType && ((forSize?.Equals(currentSelectionSize)).GetValueOrDefault(false) || (forSize == null && currentSelectionSize == null)) && !selectionBoxesDidChanged)
            {
                return(selectionBoxesVoxels);
            }

            switch (selType)
            {
            case EnumCircuitSelectionType.PlaceWire:
                GenerateSelectionVoxelBoxes(new Vec3i(1, 1, 1), true, true, true, false);
                break;

            case EnumCircuitSelectionType.PlaceComponent:
                GenerateSelectionVoxelBoxes(forSize, false, false, true, true);
                break;

            case EnumCircuitSelectionType.PlaceNothing:
                GenerateSelectionVoxelBoxes(new Vec3i(1, 1, 1), false, true, true, false);
                break;
            }

            currentSelectionSize     = forSize;
            currentSelectionType     = selType;
            selectionBoxesDidChanged = false;
            return(selectionBoxesVoxels);
        }
예제 #2
0
        public Stack <BlockPos> FindTree(IWorldAccessor world, BlockPos startPos)
        {
            Queue <Vec4i>      queue            = new Queue <Vec4i>();
            HashSet <BlockPos> checkedPositions = new HashSet <BlockPos>();
            Stack <BlockPos>   foundPositions   = new Stack <BlockPos>();

            Block block = world.BlockAccessor.GetBlock(startPos);

            if (block.Code == null)
            {
                return(foundPositions);
            }

            string treeFellingGroupCode = block.Attributes?["treeFellingGroupCode"].AsString();
            int    spreadIndex          = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0;

            if (block.Attributes?["treeFellingCanChop"].AsBool(true) == false)
            {
                return(foundPositions);
            }

            EnumTreeFellingBehavior bh = EnumTreeFellingBehavior.Chop;

            if (block is ICustomTreeFellingBehavior ctfbh)
            {
                bh = ctfbh.GetTreeFellingBehavior(startPos, null, spreadIndex);
                if (bh == EnumTreeFellingBehavior.NoChop)
                {
                    return(foundPositions);
                }
            }


            // Must start with a log
            if (spreadIndex < 2)
            {
                return(foundPositions);
            }
            if (treeFellingGroupCode == null)
            {
                return(foundPositions);
            }

            queue.Enqueue(new Vec4i(startPos.X, startPos.Y, startPos.Z, spreadIndex));
            foundPositions.Push(startPos);
            checkedPositions.Add(startPos);

            while (queue.Count > 0)
            {
                if (foundPositions.Count > 2500)
                {
                    break;
                }

                Vec4i pos = queue.Dequeue();

                block = world.BlockAccessor.GetBlock(pos.X, pos.Y, pos.Z);

                if (block is ICustomTreeFellingBehavior ctfbhh)
                {
                    bh = ctfbhh.GetTreeFellingBehavior(startPos, null, spreadIndex);
                }
                if (bh == EnumTreeFellingBehavior.NoChop)
                {
                    continue;
                }


                for (int i = 0; i < Vec3i.DirectAndIndirectNeighbours.Length; i++)
                {
                    Vec3i    facing  = Vec3i.DirectAndIndirectNeighbours[i];
                    BlockPos neibPos = new BlockPos(pos.X + facing.X, pos.Y + facing.Y, pos.Z + facing.Z);

                    float hordist  = GameMath.Sqrt(neibPos.HorDistanceSqTo(startPos.X, startPos.Z));
                    float vertdist = (neibPos.Y - startPos.Y);

                    // "only breaks blocks inside an upside down square base pyramid"
                    float f = bh == EnumTreeFellingBehavior.ChopSpreadVertical ? 0.5f : 2;
                    if (hordist - 1 >= f * vertdist)
                    {
                        continue;
                    }
                    if (checkedPositions.Contains(neibPos))
                    {
                        continue;
                    }

                    block = world.BlockAccessor.GetBlock(neibPos);
                    if (block.Code == null || block.Id == 0)
                    {
                        continue;
                    }

                    string ngcode = block.Attributes?["treeFellingGroupCode"].AsString();

                    // Only break the same type tree blocks
                    if (ngcode != treeFellingGroupCode)
                    {
                        continue;
                    }

                    // Only spread from "high to low". i.e. spread from log to leaves, but not from leaves to logs
                    int nspreadIndex = block.Attributes?["treeFellingGroupSpreadIndex"].AsInt(0) ?? 0;
                    if (pos.W < nspreadIndex)
                    {
                        continue;
                    }

                    checkedPositions.Add(neibPos);

                    if (bh == EnumTreeFellingBehavior.ChopSpreadVertical && !facing.Equals(0, 1, 0) && nspreadIndex > 0)
                    {
                        continue;
                    }

                    foundPositions.Push(neibPos.Copy());
                    queue.Enqueue(new Vec4i(neibPos.X, neibPos.Y, neibPos.Z, nspreadIndex));
                }
            }

            return(foundPositions);
        }