示例#1
0
    public static void AddBlockRepresentation(IPlanable s, Plane basement, ref Block myBlock, bool checkPlanes)
    {
        var      chunk = basement.myChunk;
        ChunkPos cpos  = basement.pos;

        switch (basement.faceIndex)
        {
        case Block.FWD_FACE_INDEX: cpos = cpos.OneBlockForward(); break;

        case Block.RIGHT_FACE_INDEX: cpos = cpos.OneBlockRight(); break;

        case Block.BACK_FACE_INDEX: cpos = cpos.OneBlockBack(); break;

        case Block.LEFT_FACE_INDEX: cpos = cpos.OneBlockLeft(); break;

        case Block.UP_FACE_INDEX: cpos = cpos.OneBlockHigher(); break;

        case Block.DOWN_FACE_INDEX: cpos = cpos.OneBlockDown(); break;
        }
        myBlock = chunk.AddBlock(cpos, s, false, checkPlanes);
        if (myBlock == null)
        {
            s.Delete(true, true, false);
            return;
        }
        else
        {
            chunk.RecalculateVisibilityAtPoint(myBlock.pos, s.GetAffectionMask());
        }
    }
示例#2
0
    public void DeleteBlock(ChunkPos pos, bool compensateStructures)
    {
        // в сиквеле стоит пересмотреть всю иерархию классов ><
        //12.06 нет, я так не думаю
        // 24.04.2019 фига сколько времени прошло
        // 26.01.2020 ну привет
        Block b = GetBlock(pos);

        if (b == null)
        {
            return;
        }
        int x = pos.x, y = pos.y, z = pos.z;

        if (b.ContainSurface())
        {
            needSurfacesUpdate = true;
        }
        var affectionMask = b.GetAffectionMask();

        b.Annihilate(compensateStructures);
        blocks.Remove(b.pos);
        RemoveBlockVisualisers(b.pos);
        if (PoolMaster.useIlluminationSystem)
        {
            RecalculateIlluminationAtPoint(pos);
        }

        if (affectionMask != 0)
        {
            if ((affectionMask & (1 << Block.FWD_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockForward())?.InitializePlane(Block.BACK_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.RIGHT_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockRight())?.InitializePlane(Block.LEFT_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.BACK_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockBack())?.InitializePlane(Block.FWD_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.UP_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockHigher())?.InitializePlane(Block.DOWN_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.LEFT_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockLeft())?.InitializePlane(Block.RIGHT_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.DOWN_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockDown())?.InitializePlane(Block.UP_FACE_INDEX);
            }
            RecalculateVisibilityAtPoint(pos, affectionMask);
        }
        shadowsUpdateRequired   = true;
        chunkDataUpdateRequired = true;
        // chunkRenderUpdateRequired = true; < в свитче
    }
示例#3
0
    public static void AddBlockRepresentation(IPlanable s, Plane basement, ref Block myBlock, bool checkPlanes)
    {
        var      chunk = basement.myChunk;
        ChunkPos cpos  = basement.pos;

        switch (basement.faceIndex)
        {
        case Block.FWD_FACE_INDEX: cpos = cpos.OneBlockForward(); break;

        case Block.RIGHT_FACE_INDEX: cpos = cpos.OneBlockRight(); break;

        case Block.BACK_FACE_INDEX: cpos = cpos.OneBlockBack(); break;

        case Block.LEFT_FACE_INDEX: cpos = cpos.OneBlockLeft(); break;

        case Block.UP_FACE_INDEX: cpos = cpos.OneBlockHigher(); break;

        case Block.DOWN_FACE_INDEX: cpos = cpos.OneBlockDown(); break;
        }
        myBlock = chunk.AddBlock(cpos, s, false, checkPlanes);
        if (myBlock == null)
        {
            s.Delete(BlockAnnihilationOrder.ManualCreationError);
            Debug.LogException(new System.Exception("new IPlanable block cannot be created"));
            return;
        }
        else
        {
            chunk.RecalculateVisibilityAtPoint(myBlock.pos, s.GetAffectionMask());
        }
    }
    private void ProtectBasementBlocks()
    {
        if (basement == null || destroyed)
        {
            return;
        }
        ChunkPos pos = basement.pos, pos2 = pos.OneBlockForward();
        var      chunk = basement.myChunk;
        byte     face  = basement.faceIndex;
        Plane    p     = null;

        if (chunk.GetBlock(pos2.OneBlockLeft())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos2)?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos2.OneBlockRight())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos.OneBlockRight())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos.OneBlockLeft())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        pos2 = pos.OneBlockBack();
        if (chunk.GetBlock(pos2.OneBlockLeft())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos2)?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        if (chunk.GetBlock(pos2.OneBlockRight())?.TryGetPlane(face, out p) ?? false)
        {
            p.BlockByStructure(this, true);
        }
        GameMaster.realMaster.afterloadRecalculationEvent -= this.ProtectBasementBlocks;
    }
示例#5
0
    public bool IsUnderOtherBlock(Plane p)
    {
        Block    b;
        ChunkPos pos  = p.pos;
        byte     face = p.faceIndex;

        switch (p.faceIndex)
        {
        case Block.FWD_FACE_INDEX: pos = pos.OneBlockForward(); face = Block.BACK_FACE_INDEX; break;

        case Block.RIGHT_FACE_INDEX: pos = pos.OneBlockRight(); face = Block.LEFT_FACE_INDEX; break;

        case Block.BACK_FACE_INDEX: pos = pos.OneBlockBack(); face = Block.FWD_FACE_INDEX; break;

        case Block.LEFT_FACE_INDEX: pos = pos.OneBlockLeft(); face = Block.RIGHT_FACE_INDEX; break;

        case Block.UP_FACE_INDEX: pos = pos.OneBlockHigher(); face = Block.DOWN_FACE_INDEX; break;

        case Block.DOWN_FACE_INDEX: pos = pos.OneBlockDown(); face = Block.UP_FACE_INDEX; break;

        default: return(false);
        }
        return(blocks.TryGetValue(pos, out b) && !b.IsFaceTransparent(face));
    }
示例#6
0
    public void RecalculateVisibilityAtPoint(ChunkPos cpos, byte affectionMask)
    {
        var b = GetBlock(cpos); if (b != null)

        {
            RefreshBlockVisualising(b);
        }

        if (affectionMask == 0)
        {
            return;
        }
        if ((affectionMask & (1 << Block.FWD_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockForward());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
        if ((affectionMask & (1 << Block.RIGHT_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockRight());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
        if ((affectionMask & (1 << Block.BACK_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockBack());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
        if ((affectionMask & (1 << Block.LEFT_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockLeft());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
        if ((affectionMask & (1 << Block.UP_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockHigher());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
        if ((affectionMask & (1 << Block.DOWN_FACE_INDEX)) != 0)
        {
            b = GetBlock(cpos.OneBlockDown());
            if (b != null)
            {
                RefreshBlockVisualising(b);
            }
        }
    }
示例#7
0
    private void Update()
    {
        if (GameMaster.loading)
        {
            return;
        }
        if (!prepared)
        {
            Prepare(GameMaster.realMaster.mainChunk);
            return;
        }
        else
        {
            if (gm.gameMode != GameMode.Play)
            {
                return;
            }
            if (needRecalculation)
            {
                lifepowerSurplus = 0f;
                if (grasslands != null)
                {
                    foreach (var g in grasslands)
                    {
                        lifepowerSurplus += g.GetLifepowerSurplus();
                    }
                }
                if (lifepowerAffectionList != null)
                {
                    foreach (var af in lifepowerAffectionList)
                    {
                        lifepowerSurplus += af.Value * MONUMENT_AFFECTION_CF;
                    }
                }
                needRecalculation = false;
            }
            //if (Input.GetKeyDown("x"))  Debug.Log(lifepowerSurplus);
            var t = Time.deltaTime;
            lifepower += t * lifepowerSurplus * GameMaster.gameSpeed;

            grasslandCreateTimer -= t;
            if (grasslandCreateTimer <= 0f)
            {
                float cost = GRASSLAND_CREATE_COST * env.environmentalConditions;
                if (lifepower > cost)
                {
                    bool      expansion = grasslands != null;
                    Grassland g         = null;
                    if (expansion)
                    {
                        g = grasslands[Random.Range(0, grasslands.Count)];
                        var          fi = g.faceIndex;
                        List <Plane> candidates = new List <Plane>();
                        Block        b, myBlock = g.plane.GetBlock(); Plane p; ChunkPos cpos = g.pos;
                        switch (fi)
                        {
                        case Block.UP_FACE_INDEX:
                        {
                            // fwd
                            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y + 1, cpos.z + 1), out b))
                            {
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(cpos.OneBlockForward(), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                            {
                                candidates.Add(p);
                            }
                            //right
                            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x + 1, cpos.y + 1, cpos.z), out b))
                            {
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(cpos.OneBlockRight(), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                            {
                                candidates.Add(p);
                            }
                            //back
                            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y + 1, cpos.z - 1), out b))
                            {
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(cpos.OneBlockBack(), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                            {
                                candidates.Add(p);
                            }
                            //left
                            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x - 1, cpos.y + 1, cpos.z), out b))
                            {
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(cpos.OneBlockLeft(), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                            {
                                candidates.Add(p);
                            }
                            //up
                            if (ceilGrasslandsSupport && myChunk.blocks.TryGetValue(cpos.OneBlockHigher(), out b))
                            {
                                if (b.TryGetPlane(Block.CEILING_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            break;
                        }

                        case Block.SURFACE_FACE_INDEX:
                        {
                            // fwd
                            if (myChunk.blocks.TryGetValue(cpos.OneBlockForward(), out b))
                            {
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y - 1, cpos.z + 1), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            //right
                            if (myChunk.blocks.TryGetValue(cpos.OneBlockRight(), out b))
                            {
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x + 1, cpos.y - 1, cpos.z), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            //back
                            if (myChunk.blocks.TryGetValue(cpos.OneBlockBack(), out b))
                            {
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y - 1, cpos.z - 1), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            //left
                            if (myChunk.blocks.TryGetValue(cpos.OneBlockLeft(), out b))
                            {
                                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (sideGrasslandsSupport && b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            else
                            {
                                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x - 1, cpos.y - 1, cpos.z), out b))
                                {
                                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                                    {
                                        candidates.Add(p);
                                    }
                                }
                            }
                            // down
                            if (sideGrasslandsSupport && myChunk.blocks.TryGetValue(cpos.OneBlockDown(), out b))
                            {
                                if (b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                                if (b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                                {
                                    candidates.Add(p);
                                }
                            }
                            // up
                            if (ceilGrasslandsSupport && myBlock.TryGetPlane(Block.CEILING_FACE_INDEX, out p) && !p.haveGrassland)
                            {
                                candidates.Add(p);
                            }
                            break;
                        }
                        }
                        if (candidates.Count > 0)
                        {
                            p = candidates[Random.Range(0, candidates.Count)];
                            g = CreateGrassland(p);
                            if (g != null)
                            {
                                SupportCreatedGrassland(g, cost);
                            }
                        }
                    }
                    else
                    {
                        var slist = myChunk.surfaces;
                        if (slist != null)
                        {
                            var   ilist = new List <int>();
                            Plane p;
                            for (int i = 0; i < slist.Length; i++)
                            {
                                p = slist[i];
                                if (MaterialIsLifeSupporting(p.materialID) && !p.haveGrassland)
                                {
                                    ilist.Add(i);
                                }
                            }
                            if (ilist.Count != 0)
                            {
                                p = slist[ilist[Random.Range(0, ilist.Count)]];
                                g = CreateGrassland(p);
                                if (g != null)
                                {
                                    SupportCreatedGrassland(g, cost);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (lifepower < 1000f && grasslands != null)
                    {
                        grasslands[Random.Range(0, grasslands.Count)].Dry();
                        lifepower        += 1000f;
                        needRecalculation = true;
                        return;
                    }
                }
                grasslandCreateTimer = GRASSLAND_CREATE_CHECK_TIME;
            }
            grasslandsUpdateTimer -= t;
            if (grasslandsUpdateTimer <= 0f && lifepower > 0f)
            {
                if (grasslands != null)
                {
                    int count = grasslands.Count;
                    if (lastUpdateIndex >= count)
                    {
                        lastUpdateIndex = 0;
                    }
                    var g = grasslands[lastUpdateIndex];
                    g.Update();
                    lifepower -= GRASSLAND_UPDATE_COST * g.level;
                    lastUpdateIndex++;
                }
                grasslandsUpdateTimer = GRASSLAND_UPDATE_TIME;
            }
        }
    }
示例#8
0
    public void CreateGrassland(float supplyEnergy)
    {
        int totalCount = grasslands.Count;

        if (lastDonoredIndex >= totalCount)
        {
            lastDonoredIndex = 0;
        }

        var g = grasslands[lastDonoredIndex];

        if (g == null)
        {
            needRecalculation = true;
            return;
        }
        var          fi = g.faceIndex;
        List <Plane> candidates = new List <Plane>();
        Block        b, myBlock = g.plane.GetBlock(); Plane p; ChunkPos cpos = g.pos;

        switch (fi)
        {
        case Block.UP_FACE_INDEX:
        {
            // fwd
            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y + 1, cpos.z + 1), out b))
            {
                if (sideGrasslandsSupport && b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(cpos.OneBlockForward(), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
            {
                candidates.Add(p);
            }
            //right
            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x + 1, cpos.y + 1, cpos.z), out b))
            {
                if (sideGrasslandsSupport && b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(cpos.OneBlockRight(), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
            {
                candidates.Add(p);
            }
            //back
            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y + 1, cpos.z - 1), out b))
            {
                if (sideGrasslandsSupport && b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(cpos.OneBlockBack(), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
            {
                candidates.Add(p);
            }
            //left
            if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x - 1, cpos.y + 1, cpos.z), out b))
            {
                if (sideGrasslandsSupport && b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(cpos.OneBlockLeft(), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            if (sideGrasslandsSupport && myBlock.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
            {
                candidates.Add(p);
            }
            //up
            if (ceilGrasslandsSupport && myChunk.blocks.TryGetValue(cpos.OneBlockHigher(), out b))
            {
                if (b.TryGetPlane(Block.CEILING_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            break;
        }

        case Block.SURFACE_FACE_INDEX:
        {
            // fwd
            if (myChunk.blocks.TryGetValue(cpos.OneBlockForward(), out b))
            {
                if (sideGrasslandsSupport && b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y - 1, cpos.z + 1), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            //right
            if (myChunk.blocks.TryGetValue(cpos.OneBlockRight(), out b))
            {
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (sideGrasslandsSupport && b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x + 1, cpos.y - 1, cpos.z), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            //back
            if (myChunk.blocks.TryGetValue(cpos.OneBlockBack(), out b))
            {
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (sideGrasslandsSupport && b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x, cpos.y - 1, cpos.z - 1), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            //left
            if (myChunk.blocks.TryGetValue(cpos.OneBlockLeft(), out b))
            {
                if (b.TryGetPlane(Block.SURFACE_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (sideGrasslandsSupport && b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            else
            {
                if (myChunk.blocks.TryGetValue(new ChunkPos(cpos.x - 1, cpos.y - 1, cpos.z), out b))
                {
                    if (b.TryGetPlane(Block.UP_FACE_INDEX, out p) && !p.haveGrassland)
                    {
                        candidates.Add(p);
                    }
                }
            }
            // down
            if (sideGrasslandsSupport && myChunk.blocks.TryGetValue(cpos.OneBlockDown(), out b))
            {
                if (b.TryGetPlane(Block.FWD_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.RIGHT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.BACK_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
                if (b.TryGetPlane(Block.LEFT_FACE_INDEX, out p) && !p.haveGrassland)
                {
                    candidates.Add(p);
                }
            }
            // up
            if (ceilGrasslandsSupport && myBlock.TryGetPlane(Block.CEILING_FACE_INDEX, out p) && !p.haveGrassland)
            {
                candidates.Add(p);
            }
            break;
        }
        }
        if (candidates.Count > 0)
        {
            bool IsNotSuitable(Plane px)
            {
                return(!px.IsSuitableForGrassland());
            }

            candidates.RemoveAll(IsNotSuitable);
            if (candidates.Count > 0)
            {
                p = candidates[Random.Range(0, candidates.Count)];
                CreateGrassland(p, supplyEnergy);
            }
        }
        lastDonoredIndex++;
    }