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); }
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); } } } }
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); }
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(); } } }
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(); } }
/// <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); }
/// <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); }