Пример #1
0
    public static void ScatterNodes(Queue <Vector3i> nodes, bool generator)
    {
        while (nodes.Count > 0)
        {
            Vector3i pos = nodes.Dequeue();

            Block block = Map.GetBlock(pos.x, pos.y, pos.z);
            int   light = MapLight.GetSunlight(pos.x, pos.y, pos.z) - block.GetLightStep();

            if (light <= LightUtils.MinLight)
            {
                continue;
            }

            for (int i = 0; i < 6; i++)
            {
                Vector3i nextPos = pos + Vector3i.directions[i];

                if (Map.InBounds(nextPos.x, nextPos.y, nextPos.z))
                {
                    block = Map.GetBlock(nextPos.x, nextPos.y, nextPos.z);

                    if (block.IsTransparent() && SetMax((byte)light, nextPos.x, nextPos.y, nextPos.z))
                    {
                        nodes.Enqueue(nextPos);

                        if (!generator)
                        {
                            Map.FlagChunkForUpdate(nextPos.x, nextPos.y, nextPos.z);
                        }
                    }
                }
            }
        }
    }
Пример #2
0
    // Scatters the initial light throughout the map.
    public static void Scatter(int worldX, int worldZ, Queue <Vector3i> sunNodes, Queue <Vector3i> lightNodes)
    {
        for (int x = worldX; x < worldX + Chunk.Size; x++)
        {
            for (int z = worldZ; z < worldZ + Chunk.Size; z++)
            {
                int ray  = MapLight.GetRay(x, z);
                int maxY = ComputeMaxY(x, z, ray);

                for (int y = ray; y <= maxY; y++)
                {
                    if (y >= Map.Height)
                    {
                        continue;
                    }

                    sunNodes.Enqueue(new Vector3i(x, y, z));
                    byte light = Map.GetBlock(x, y, z).LightEmitted();

                    if (light > LightUtils.MinLight)
                    {
                        MapLight.SetLight(x, y, z, light);
                        lightNodes.Enqueue(new Vector3i(x, y, z));
                    }
                }
            }
        }

        ScatterNodes(sunNodes, true);
        BlockLightEngine.ScatterNodes(lightNodes, true);
    }
Пример #3
0
    public static Color32 GetBlockLight(Vector3i pos)
    {
        byte light = lightOutput[MapLight.GetLightSafe(pos.x, pos.y, pos.z)];
        byte sun   = lightOutput[MapLight.GetSunlightSafe(pos.x, pos.y, pos.z)];

        return(new Color32(light, light, light, sun));
    }
Пример #4
0
    public static Color32 GetBlockLight(int x, int y, int z)
    {
        byte light = lightOutput[MapLight.GetLightSafe(x, y, z)];
        byte sun   = lightOutput[MapLight.GetSunlightSafe(x, y, z)];

        return(new Color32(light, light, light, sun));
    }
Пример #5
0
    public static void SetBlocksAdvanced(List <BlockInstance> blocks, bool undo)
    {
        List <BlockInstance> prevBlocks = new List <BlockInstance>();

        for (int i = 0; i < blocks.Count; i++)
        {
            BlockInstance blockInst = blocks[i];

            int x = blockInst.x;
            int y = blockInst.y;
            int z = blockInst.z;

            if (!InBounds(x, y, z))
            {
                continue;
            }

            if (!blockInst.block.CanPlace(Vector3i.zero, x, y, z))
            {
                continue;
            }

            BlockInstance prevInst = new BlockInstance(GetBlock(x, y, z), x, y, z);

            if (blockInst.block.ID == BlockID.Air)
            {
                if (!prevInst.block.CanDelete())
                {
                    continue;
                }
                else
                {
                    prevInst.block.OnDelete(x, y, z);
                }
            }
            else
            {
                blockInst.block.OnPlace(Vector3i.zero, x, y, z);
            }

            if (undo)
            {
                prevBlocks.Add(new BlockInstance(GetBlock(x, y, z), x, y, z));
            }

            SetBlock(x, y, z, blocks[i].block);

            MapLight.RecomputeLighting(x, y, z);
            FlagChunkForUpdate(x, y, z);
        }

        UpdateMeshes();

        if (undo)
        {
            UndoManager.RegisterAction(prevBlocks, blocks);
        }
    }
Пример #6
0
    // Returns the highest point in the world between this column and each neighbor column.
    private static int ComputeMaxY(int x, int z, int ray)
    {
        ray = Mathf.Max(ray, MapLight.GetRaySafe(x - 1, z));
        ray = Mathf.Max(ray, MapLight.GetRaySafe(x + 1, z));
        ray = Mathf.Max(ray, MapLight.GetRaySafe(x, z - 1));
        ray = Mathf.Max(ray, MapLight.GetRaySafe(x, z + 1));

        return(ray);
    }
Пример #7
0
    public static void Recompute(Vector3i pos, Queue <Vector3i> nodes)
    {
        int oldSunHeight = MapLight.GetRay(pos.x, pos.z);

        ComputeRayAtPosition(pos.x, pos.z);
        int newSunHeight = MapLight.GetRay(pos.x, pos.z);

        if (newSunHeight < oldSunHeight)
        {
            for (int ty = newSunHeight; ty <= oldSunHeight; ty++)
            {
                pos.y = ty;

                if (ty < Map.Height)
                {
                    MapLight.SetSunlight(pos.x, pos.y, pos.z, LightUtils.MinLight);
                }

                nodes.Enqueue(pos);
            }

            ScatterNodes(nodes, false);
            return;
        }

        if (newSunHeight > oldSunHeight)
        {
            for (int ty = oldSunHeight; ty <= newSunHeight; ty++)
            {
                pos.y = ty;

                if (ty < Map.Height)
                {
                    MapLight.SetSunlight(pos.x, pos.y, pos.z, LightUtils.MaxLight);
                }

                nodes.Enqueue(pos);
            }

            RemoveNodes(nodes);
            return;
        }

        if (newSunHeight == oldSunHeight)
        {
            if (Map.GetBlock(pos.x, pos.y, pos.z).IsTransparent())
            {
                Update(pos, nodes);
            }
            else
            {
                Remove(pos, nodes);
            }
        }
    }
Пример #8
0
    private static void RemoveNodes(Queue <Vector3i> nodes)
    {
        Queue <Vector3i> newLights = new Queue <Vector3i>();

        while (nodes.Count > 0)
        {
            Vector3i pos = nodes.Dequeue();

            if (pos.y < 0 || pos.y >= Map.Height)
            {
                continue;
            }

            int light = MapLight.GetLight(pos.x, pos.y, pos.z) - 1;
            MapLight.SetLight(pos.x, pos.y, pos.z, LightUtils.MinLight);

            if (light <= LightUtils.MinLight)
            {
                continue;
            }

            for (int i = 0; i < 6; i++)
            {
                Vector3i nextPos = pos + Vector3i.directions[i];

                if (Map.InBounds(nextPos.x, nextPos.z))
                {
                    Block block = Map.GetBlock(nextPos.x, nextPos.y, nextPos.z);

                    if (block.IsTransparent())
                    {
                        if (MapLight.GetLight(nextPos.x, nextPos.y, nextPos.z) <= light)
                        {
                            nodes.Enqueue(nextPos);
                        }
                        else
                        {
                            newLights.Enqueue(nextPos);
                        }
                    }

                    if (block.LightEmitted() > LightUtils.MinLight)
                    {
                        newLights.Enqueue(nextPos);
                    }

                    Map.FlagChunkForUpdate(nextPos.x, nextPos.y, nextPos.z);
                }
            }
        }

        ScatterNodes(newLights, false);
    }
Пример #9
0
    public static bool SetMax(byte light, int x, int y, int z)
    {
        byte oldLight = MapLight.GetLight(x, y, z);

        if (oldLight < light)
        {
            MapLight.SetLight(x, y, z, light);
            return(true);
        }

        return(false);
    }
Пример #10
0
    private void QueueBlocksForUnflowing()
    {
        for (int i = 0; i < blocksToUnflow.Count; i++)
        {
            BlockInstance b = blocksToUnflow[i];
            MapLight.RecomputeLighting(b.x, b.y, b.z);
            Map.FlagChunkForUpdate(b.x, b.y, b.z);

            unflowQueue.Enqueue(blocksToUnflow[i]);
        }

        Map.UpdateMeshes();
        blocksToUnflow = new List <BlockInstance>(128);
    }
Пример #11
0
    private static bool SetMax(byte light, int x, int y, int z)
    {
        if (y >= MapLight.GetRay(x, z))
        {
            return(false);
        }

        byte oldLight = MapLight.GetSunlight(x, y, z);

        if (oldLight < light)
        {
            MapLight.SetSunlight(x, y, z, light);
            return(true);
        }

        return(false);
    }
Пример #12
0
    public static void Recompute(Vector3i pos, Queue <Vector3i> nodes)
    {
        byte oldLight = MapLight.GetLight(pos.x, pos.y, pos.z);
        byte light    = Map.GetBlock(pos.x, pos.y, pos.z).LightEmitted();

        if (oldLight > light)
        {
            Remove(pos, nodes);
        }

        if (light > LightUtils.MinLight)
        {
            MapLight.SetLight(pos.x, pos.y, pos.z, light);
            Scatter(pos, nodes);
        }
        else
        {
            Update(pos, nodes);
        }
    }
Пример #13
0
    protected Vector3 TryFindLand(Vector3i center)
    {
        Vector3i?land = null;

        for (int x = center.x - 20; x <= center.x + 20; x++)
        {
            for (int z = center.z - 20; z <= center.z + 20; z++)
            {
                int   height  = MapLight.GetRaySafe(x, z);
                Block surface = Map.GetBlockSafe(x, height - 1, z);

                if (!surface.IsFluid())
                {
                    Vector3i current = new Vector3i(x, height, z);

                    if (!land.HasValue)
                    {
                        land = current;
                    }
                    else
                    {
                        int dis    = center.DistanceSquared(current);
                        int oldDis = center.DistanceSquared(land.Value);

                        if (dis < oldDis)
                        {
                            land = current;
                        }
                    }
                }
            }
        }

        if (land.HasValue)
        {
            return(land.Value.ToVector3());
        }

        return(new Vector3(center.x, MapLight.GetRay(center.x, center.z), center.z));
    }
Пример #14
0
    public static void SetBlockAdvanced(int x, int y, int z, Block block, Vector3i normal, bool undo)
    {
        if (InBounds(x, y, z))
        {
            if (!block.CanPlace(normal, x, y, z))
            {
                return;
            }

            BlockInstance prevInst = new BlockInstance(GetBlock(x, y, z), x, y, z);
            BlockInstance newBlock = new BlockInstance(block, x, y, z);

            if (block.ID == BlockID.Air)
            {
                if (!prevInst.block.CanDelete())
                {
                    return;
                }

                prevInst.block.OnDelete(x, y, z);
            }
            else
            {
                block.OnPlace(normal, x, y, z);
            }

            if (undo)
            {
                UndoManager.RegisterAction(prevInst, newBlock);
            }

            SetBlock(x, y, z, block);

            MapLight.RecomputeLighting(x, y, z);

            FlagChunkForUpdate(x, y, z);
            UpdateMeshes();
        }
    }
Пример #15
0
 public static void BeginPlay()
 {
     MapLight.GenerateAllLight();
 }
Пример #16
0
 private static void Remove(Vector3i pos, Queue <Vector3i> nodes)
 {
     MapLight.SetLight(pos.x, pos.y, pos.z, LightUtils.MaxLight);
     nodes.Enqueue(pos);
     RemoveNodes(nodes);
 }
Пример #17
0
    private static void ComputeRayAtPosition(int x, int z)
    {
        int surface = Map.GetSurface(x, z);

        MapLight.SetRay(x, z, (byte)(surface + 1));
    }