Пример #1
0
        public BoundingBox?GetBoundingBox(IWorld world, Coordinates3D coordinates)
        {
            // TODO: Block-specific bounding boxes
            var id = world.GetBlockID(coordinates);

            if (id == 0)
            {
                return(null);
            }
            var provider = BlockProviders[id];

            return(provider.BoundingBox);
        }
Пример #2
0
        void ScheduleUpdatesForChunk(IWorld world, IChunk chunk)
        {
            int _x = chunk.Coordinates.X * Chunk.Width;
            int _z = chunk.Coordinates.Z * Chunk.Depth;

            for (byte x = 0; x < Chunk.Width; x++)
            {
                for (byte z = 0; z < Chunk.Depth; z++)
                {
                    for (int y = 0; y < chunk.GetHeight(x, z); y++)
                    {
                        var coords = new Coordinates3D(_x + x, y, _z + z);
                        var id     = world.GetBlockID(coords);
                        if (id == 0)
                        {
                            continue;
                        }
                        var provider = BlockRepository.GetBlockProvider(id);
                        provider.BlockLoadedFromChunk(coords, this, world);
                    }
                }
            }
        }
Пример #3
0
 public static BlockFace CoordinatesToBlockFace(Coordinates3D face)
 {
     if (face == Coordinates3D.Down)
     {
         return(BlockFace.NegativeY);
     }
     if (face == Coordinates3D.Up)
     {
         return(BlockFace.PositiveY);
     }
     if (face == Coordinates3D.Backwards)
     {
         return(BlockFace.NegativeZ);
     }
     if (face == Coordinates3D.Forwards)
     {
         return(BlockFace.PositiveZ);
     }
     if (face == Coordinates3D.Left)
     {
         return(BlockFace.NegativeX);
     }
     return(BlockFace.PositiveX);
 }
Пример #4
0
        public static void Main(string[] args)
        {
            if (File.Exists("config.yaml"))
            {
                var deserializer = new Deserializer(ignoreUnmatched: true);
                using (var file = File.OpenText("config.yaml"))
                    Configuration = deserializer.Deserialize <Configuration>(file);
            }
            else
            {
                Configuration = new Configuration();
            }
            var serializer = new Serializer();

            using (var writer = new StreamWriter("config.yaml"))
                serializer.Serialize(writer, Configuration);

            Server = new MultiplayerServer();
            Server.AddLogProvider(new ConsoleLogProvider(LogCategory.Notice | LogCategory.Warning | LogCategory.Error | LogCategory.Debug));
            #if DEBUG
            Server.AddLogProvider(new FileLogProvider(new StreamWriter("packets.log", false), LogCategory.Packets));
            #endif
            if (Configuration.Debug.DeleteWorldOnStartup)
            {
                if (Directory.Exists("world"))
                {
                    Directory.Delete("world", true);
                }
            }
            if (Configuration.Debug.DeletePlayersOnStartup)
            {
                if (Directory.Exists("players"))
                {
                    Directory.Delete("players", true);
                }
            }
            IWorld world;
            try
            {
                world = World.LoadWorld("world");
                Server.AddWorld(world);
            }
            catch
            {
                world = new World("default", new StandardGenerator());
                world.BlockRepository = Server.BlockRepository;
                world.Save("world");
                Server.AddWorld(world);
                Server.Log(LogCategory.Notice, "Generating world around spawn point...");
                for (int x = -5; x < 5; x++)
                {
                    for (int z = -5; z < 5; z++)
                    {
                        world.GetChunk(new Coordinates2D(x, z));
                    }
                    int progress = (int)(((x + 5) / 10.0) * 100);
                    if (progress % 10 == 0)
                    {
                        Server.Log(LogCategory.Notice, "{0}% complete", progress + 10);
                    }
                }
                Server.Log(LogCategory.Notice, "Simulating the world for a moment...");
                for (int x = -5; x < 5; x++)
                {
                    for (int z = -5; z < 5; z++)
                    {
                        var chunk = world.GetChunk(new Coordinates2D(x, z));
                        for (byte _x = 0; _x < Chunk.Width; _x++)
                        {
                            for (byte _z = 0; _z < Chunk.Depth; _z++)
                            {
                                for (int _y = 0; _y < chunk.GetHeight(_x, _z); _y++)
                                {
                                    var coords   = new Coordinates3D(x + _x, _y, z + _z);
                                    var data     = world.GetBlockData(coords);
                                    var provider = world.BlockRepository.GetBlockProvider(data.ID);
                                    provider.BlockUpdate(data, data, Server, world);
                                }
                            }
                        }
                    }
                    int progress = (int)(((x + 5) / 10.0) * 100);
                    if (progress % 10 == 0)
                    {
                        Server.Log(LogCategory.Notice, "{0}% complete", progress + 10);
                    }
                }
            }
            CommandManager              = new CommandManager();
            Server.ChatMessageReceived += HandleChatMessageReceived;
            Server.Start(new IPEndPoint(IPAddress.Parse(Configuration.ServerAddress), Configuration.ServerPort));
            Console.CancelKeyPress += HandleCancelKeyPress;
            while (true)
            {
                Thread.Sleep(1000 * 30); // TODO: Allow users to customize world save interval
                foreach (var w in Server.Worlds)
                {
                    w.Save();
                }
            }
        }
Пример #5
0
        public static void Main(string[] args)
        {
            Server = new MultiplayerServer();

            Server.AddLogProvider(new ConsoleLogProvider(LogCategory.Notice | LogCategory.Warning | LogCategory.Error | LogCategory.Debug));
#if DEBUG
            Server.AddLogProvider(new FileLogProvider(new StreamWriter("packets.log", false), LogCategory.Packets));
#endif

            ServerConfiguration = Configuration.LoadConfiguration <ServerConfiguration>("config.yaml");

            var buckets = ServerConfiguration.Debug?.Profiler?.Buckets?.Split(',');
            if (buckets != null)
            {
                foreach (var bucket in buckets)
                {
                    Profiler.EnableBucket(bucket.Trim());
                }
            }

            if (ServerConfiguration.Debug.DeleteWorldOnStartup)
            {
                if (Directory.Exists("world"))
                {
                    Directory.Delete("world", true);
                }
            }
            if (ServerConfiguration.Debug.DeletePlayersOnStartup)
            {
                if (Directory.Exists("players"))
                {
                    Directory.Delete("players", true);
                }
            }
            IWorld world;
            try
            {
                world = World.LoadWorld("world");
                Server.AddWorld(world);
            }
            catch
            {
                world = new World("default", new StandardGenerator());
                world.BlockRepository = Server.BlockRepository;
                world.Save("world");
                Server.AddWorld(world);
                Server.Log(LogCategory.Notice, "Generating world around spawn point...");
                for (int x = -5; x < 5; x++)
                {
                    for (int z = -5; z < 5; z++)
                    {
                        world.GetChunk(new Coordinates2D(x, z));
                    }
                    int progress = (int)(((x + 5) / 10.0) * 100);
                    if (progress % 10 == 0)
                    {
                        Server.Log(LogCategory.Notice, "{0}% complete", progress + 10);
                    }
                }
                Server.Log(LogCategory.Notice, "Simulating the world for a moment...");
                for (int x = -5; x < 5; x++)
                {
                    for (int z = -5; z < 5; z++)
                    {
                        var chunk = world.GetChunk(new Coordinates2D(x, z));
                        for (byte _x = 0; _x < Chunk.Width; _x++)
                        {
                            for (byte _z = 0; _z < Chunk.Depth; _z++)
                            {
                                for (int _y = 0; _y < chunk.GetHeight(_x, _z); _y++)
                                {
                                    var coords   = new Coordinates3D(x + _x, _y, z + _z);
                                    var data     = world.GetBlockData(coords);
                                    var provider = world.BlockRepository.GetBlockProvider(data.ID);
                                    provider.BlockUpdate(data, data, Server, world);
                                }
                            }
                        }
                    }
                    int progress = (int)(((x + 5) / 10.0) * 100);
                    if (progress % 10 == 0)
                    {
                        Server.Log(LogCategory.Notice, "{0}% complete", progress + 10);
                    }
                }
                Server.Log(LogCategory.Notice, "Lighting the world (this will take a moment)...");
                foreach (var lighter in Server.WorldLighters)
                {
                    while (lighter.TryLightNext())
                    {
                        ;
                    }
                }
            }
            world.Save();
            CommandManager              = new CommandManager();
            Server.ChatMessageReceived += HandleChatMessageReceived;
            Server.Start(new IPEndPoint(IPAddress.Parse(ServerConfiguration.ServerAddress), ServerConfiguration.ServerPort));
            Console.CancelKeyPress += HandleCancelKeyPress;
            Server.Scheduler.ScheduleEvent("world.save", null,
                                           TimeSpan.FromSeconds(ServerConfiguration.WorldSaveInterval), SaveWorlds);
            while (true)
            {
                Thread.Yield();
            }
        }
Пример #6
0
        /// <summary>
        /// Performs terrain collision tests and adjusts the Z-axis velocity accordingly
        /// </summary>
        /// <returns>True if the entity collides with the terrain</returns>
        private bool AdjustVelocityZ(IAABBEntity entity, IWorld world, out Vector3 collision, out Vector3 collisionDirection)
        {
            collision          = Vector3.Zero;
            collisionDirection = Vector3.Zero;
            if (entity.Velocity.Z == 0)
            {
                return(false);
            }
            // Do some enviornment guessing to improve speed
            int minX = (int)entity.Position.X - (entity.Position.X < 0 ? 1 : 0);
            int maxX = (int)(entity.Position.X + entity.Size.Depth) - (entity.Position.X < 0 ? 1 : 0);
            int minY = (int)entity.Position.Y - (entity.Position.Y < 0 ? 1 : 0);
            int maxY = (int)(entity.Position.Y + entity.Size.Width) - (entity.Position.Y < 0 ? 1 : 0);
            int minZ, maxZ;

            // Expand bounding box to include area to be tested
            if (entity.Velocity.Z < 0)
            {
                TempBoundingBox = new BoundingBox(
                    new Vector3(entity.BoundingBox.Min.X, entity.BoundingBox.Min.Y, entity.BoundingBox.Min.Z + entity.Velocity.Z),
                    entity.BoundingBox.Max);

                maxZ = (int)(TempBoundingBox.Max.Z);
                minZ = (int)(TempBoundingBox.Min.Z + entity.Velocity.Z) - 1;
            }
            else
            {
                TempBoundingBox = new BoundingBox(
                    entity.BoundingBox.Min,
                    new Vector3(entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y, entity.BoundingBox.Max.Z + entity.Velocity.Z)
                    );
                minZ = (int)(entity.BoundingBox.Min.Z);
                maxZ = (int)(entity.BoundingBox.Max.Z + entity.Velocity.Z) + 1;
            }

            // Do terrain checks
            double?     collisionPoint = null;
            BoundingBox blockBox;

            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <= maxY; y++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        var position    = new Coordinates3D(x, y, z);
                        var boundingBox = BlockPhysicsProvider.GetBoundingBox(world, position);
                        if (boundingBox == null)
                        {
                            continue;
                        }
                        blockBox = boundingBox.Value.OffsetBy(position + new Vector3(0.5));
                        if (TempBoundingBox.Intersects(blockBox))
                        {
                            if (entity.Velocity.Z < 0)
                            {
                                if (!collisionPoint.HasValue)
                                {
                                    collisionPoint = blockBox.Max.Z;
                                }
                                else if (collisionPoint.Value < blockBox.Max.Z)
                                {
                                    collisionPoint = blockBox.Max.Z;
                                }
                            }
                            else
                            {
                                if (!collisionPoint.HasValue)
                                {
                                    collisionPoint = blockBox.Min.Z;
                                }
                                else if (collisionPoint.Value > blockBox.Min.Z)
                                {
                                    collisionPoint = blockBox.Min.Z;
                                }
                            }
                            collision = position;
                        }
                    }
                }
            }

            if (collisionPoint != null)
            {
                if (entity.Velocity.Z < 0)
                {
                    entity.Velocity = new Vector3(
                        entity.Velocity.X,
                        entity.Velocity.Y,
                        entity.Velocity.Z - (TempBoundingBox.Min.Z - collisionPoint.Value));
                    collisionDirection = Vector3.Backwards;
                }
                else if (entity.Velocity.Z > 0)
                {
                    entity.Velocity = new Vector3(
                        entity.Velocity.X,
                        entity.Velocity.Y,
                        entity.Velocity.Z - (TempBoundingBox.Max.Z - collisionPoint.Value));
                    collisionDirection = Vector3.Forwards;
                }
                return(true);
            }

            return(false);
        }
Пример #7
0
        /// <summary>
        /// Performs terrain collision tests and adjusts the Y-axis velocity accordingly
        /// </summary>
        /// <returns>True if the entity collides with the terrain</returns>
        private bool AdjustVelocityY(IAABBEntity entity, IWorld world, out Vector3 collision, out Vector3 collisionDirection)
        {
            collision          = Vector3.Zero;
            collisionDirection = Vector3.Zero;
            if (entity.Velocity.Y == 0)
            {
                return(false);
            }
            // Do some enviornment guessing to improve speed
            int minX = (int)entity.Position.X - (entity.Position.X < 0 ? 1 : 0);
            int maxX = (int)(entity.Position.X + entity.Size.Width) - (entity.Position.X < 0 ? 1 : 0);
            int minZ = (int)entity.Position.Z - (entity.Position.Z < 0 ? 1 : 0);
            int maxZ = (int)(entity.Position.Z + entity.Size.Depth) - (entity.Position.Z < 0 ? 1 : 0);
            int minY, maxY;

            // Expand bounding box to include area to be tested
            if (entity.Velocity.Y < 0)
            {
                TempBoundingBox = new BoundingBox(
                    new Vector3(entity.BoundingBox.Min.X, entity.BoundingBox.Min.Y + entity.Velocity.Y, entity.BoundingBox.Min.Z),
                    entity.BoundingBox.Max);

                maxY = (int)(TempBoundingBox.Max.Y);
                minY = (int)(TempBoundingBox.Min.Y + entity.Velocity.Y) - 1;
            }
            else
            {
                TempBoundingBox = new BoundingBox(
                    entity.BoundingBox.Min,
                    new Vector3(entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y + entity.Velocity.Y, entity.BoundingBox.Max.Z));
                minY = (int)(entity.BoundingBox.Min.Y);
                maxY = (int)(entity.BoundingBox.Max.Y + entity.Velocity.Y) + 1;
            }

            // Clamp Y into map boundaries
            if (minY < 0)
            {
                minY = 0;
            }
            if (minY >= TrueCraft.Core.World.World.Height)
            {
                minY = TrueCraft.Core.World.World.Height - 1;
            }
            if (maxY < 0)
            {
                maxY = 0;
            }
            if (maxY >= TrueCraft.Core.World.World.Height)
            {
                maxY = TrueCraft.Core.World.World.Height - 1;
            }

            // Do terrain checks
            double?     collisionPoint = null;
            BoundingBox blockBox;

            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <= maxY; y++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        var position = new Coordinates3D(x, y, z);
                        if (!World.IsValidPosition(position))
                        {
                            continue;
                        }
                        var boundingBox = BlockPhysicsProvider.GetBoundingBox(world, position);
                        if (boundingBox == null)
                        {
                            continue;
                        }
                        blockBox = boundingBox.Value.OffsetBy(position + new Vector3(0.5));
                        if (TempBoundingBox.Intersects(blockBox))
                        {
                            if (entity.Velocity.Y < 0)
                            {
                                if (!collisionPoint.HasValue)
                                {
                                    collisionPoint = blockBox.Max.Y;
                                }
                                else if (collisionPoint.Value < blockBox.Max.Y)
                                {
                                    collisionPoint = blockBox.Max.Y;
                                }
                            }
                            else
                            {
                                if (!collisionPoint.HasValue)
                                {
                                    collisionPoint = blockBox.Min.Y;
                                }
                                else if (collisionPoint.Value > blockBox.Min.Y)
                                {
                                    collisionPoint = blockBox.Min.Y;
                                }
                            }
                            collision = position;
                        }
                    }
                }
            }

            if (collisionPoint != null)
            {
                if (entity.Velocity.Y < 0)
                {
                    // TODO: Do block event
                    //var block = world.GetBlock(collision);
                    //block.OnBlockWalkedOn(world, collision, this);
                    entity.Velocity = new Vector3(entity.Velocity.X,
                                                  entity.Velocity.Y + (collisionPoint.Value - TempBoundingBox.Min.Y),
                                                  entity.Velocity.Z);
                    collisionDirection = Vector3.Down;
                }
                else if (entity.Velocity.Y > 0)
                {
                    entity.Velocity = new Vector3(entity.Velocity.X,
                                                  entity.Velocity.Y - (TempBoundingBox.Max.Y - collisionPoint.Value),
                                                  entity.Velocity.Z);
                    collisionDirection = Vector3.Up;
                }
                return(true);
            }

            return(false);
        }