Пример #1
0
        public void Run(World world)
        {
            if (Area.Size > 16 * 16 * 128) {
                Console.WriteLine("[LightingEngine] Tried to run a too big update");
                return;
            }

            for (int x = Area.X1; x <= Area.X2; x++) {
                for (int z = Area.Z1; z <= Area.Z2; z++) {
                    if (!world.IsLoaded(x, z))
                        continue;
                    for (int y = Area.Y1; y <= Area.Y2; y++) {
                        int oldLight = world.GetLight(Type, x, y, z);
                        int newLight = 0;

                        int blockType = world.GetBlockType(x, y, z);
                        int lightBlocked = Math.Max(1, Block.LightAbsorbs[blockType]);
                        int lightEmitted = 0;
                        if (Type == LightType.Sky) {
                            // Blocks directly hit by sky light scatter light
                            if (world.RecievesSkyLight(x, y, z))
                                lightEmitted = 15;
                        } else if (Type == LightType.Block) {
                            lightEmitted = Block.LightEmits[blockType];
                        }

                        // All light gets absorbed, no need to check neighbors
                        if (lightBlocked >= 15 && lightEmitted == 0)
                            newLight = 0;
                        else {
                            // Find the highest light from the neighbors
                            newLight = Math.Max(0, GetHighestNeighbor(world, x, y, z) - lightBlocked);

                            // Emitted light always takes precedence
                            if (lightEmitted > newLight)
                                newLight = lightEmitted;
                        }

                        // Light changed, scatter it to neighbors
                        if (oldLight != newLight) {
                            world.SetLight(Type, x, y, z, newLight);

                            int neighborLight = Math.Max(0, newLight - 1);
                            // Definitely update blocks we already passed in the loop
                            engine.TryUpdateTile(Type, x - 1, y, z, neighborLight);
                            engine.TryUpdateTile(Type, x, y - 1, z, neighborLight);
                            engine.TryUpdateTile(Type, x, y, z - 1, neighborLight);

                            // Only update following blocks if we aren't going to update them in this loop
                            if (x + 1 >= Area.X2)
                                engine.TryUpdateTile(Type, x + 1, y, z, neighborLight);
                            if (y + 1 >= Area.Y2)
                                engine.TryUpdateTile(Type, x, y + 1, z, neighborLight);
                            if (z + 1 >= Area.Z2)
                                engine.TryUpdateTile(Type, x, y, z + 1, neighborLight);
                        }
                    }
                }
            }
        }