diff --git a/TrueCraft.API/World/IWorld.cs b/TrueCraft.API/World/IWorld.cs
index 23ff9cd..fd024c1 100644
--- a/TrueCraft.API/World/IWorld.cs
+++ b/TrueCraft.API/World/IWorld.cs
@@ -27,5 +27,6 @@ namespace TrueCraft.API.World
void SetBlockLight(Coordinates3D coordinates, byte value);
bool IsValidPosition(Coordinates3D position);
void Save();
+ void Save(string path);
}
}
\ No newline at end of file
diff --git a/TrueCraft.Core/World/Chunk.cs b/TrueCraft.Core/World/Chunk.cs
index 59ea069..3da4322 100644
--- a/TrueCraft.Core/World/Chunk.cs
+++ b/TrueCraft.Core/World/Chunk.cs
@@ -209,23 +209,34 @@ namespace TrueCraft.Core.World
var chunk = (NbtCompound)Serializer.Serialize(this, tagName, true);
var entities = new NbtList("Entities", NbtTagType.Compound);
chunk.Add(entities);
- // TODO: Save block data
+ chunk.Add(new NbtByteArray("Blocks", Blocks));
+ chunk.Add(new NbtByteArray("Data", Metadata.Data));
+ chunk.Add(new NbtByteArray("SkyLight", SkyLight.Data));
+ chunk.Add(new NbtByteArray("BlockLight", BlockLight.Data));
+ // TODO: Tile entities, entities
return chunk;
}
public void Deserialize(NbtTag value)
{
- IsModified = true;
var chunk = (Chunk)Serializer.Deserialize(value, true);
+ var tag = (NbtCompound)value;
- this.Biomes = chunk.Biomes;
- this.HeightMap = chunk.HeightMap;
- this.LastUpdate = chunk.LastUpdate;
- this.TerrainPopulated = chunk.TerrainPopulated;
- this.X = chunk.X;
- this.Z = chunk.Z;
+ Biomes = chunk.Biomes;
+ HeightMap = chunk.HeightMap;
+ LastUpdate = chunk.LastUpdate;
+ TerrainPopulated = chunk.TerrainPopulated;
+ X = tag["xPos"].IntValue;
+ Z = tag["zPos"].IntValue;
+ Blocks = tag["Blocks"].ByteArrayValue;
+ Metadata = new NibbleArray();
+ Metadata.Data = tag["Data"].ByteArrayValue;
+ BlockLight = new NibbleArray();
+ BlockLight.Data = tag["BlockLight"].ByteArrayValue;
+ SkyLight = new NibbleArray();
+ SkyLight.Data = tag["SkyLight"].ByteArrayValue;
- // TODO: Load block data
+ // TODO: Tile entities, entities
}
}
}
diff --git a/TrueCraft.Core/World/Region.cs b/TrueCraft.Core/World/Region.cs
index 0b43996..caa42c5 100644
--- a/TrueCraft.Core/World/Region.cs
+++ b/TrueCraft.Core/World/Region.cs
@@ -94,54 +94,8 @@ namespace TrueCraft.Core.World
var nbt = new NbtFile();
nbt.LoadFromStream(regionFile, NbtCompression.ZLib, null);
var chunk = Chunk.FromNbt(nbt);
- Chunks.Add(position, (IChunk)chunk);
- break;
- default:
- throw new InvalidDataException("Invalid compression scheme provided by region file.");
- }
- }
- }
- else if (World.ChunkProvider == null)
- throw new ArgumentException("The requested chunk is not loaded.", "position");
- else
- GenerateChunk(position);
- }
- return Chunks[position];
- }
- }
-
- ///
- /// Retrieves the requested chunk from the region, without using the
- /// world generator if it does not exist.
- ///
- /// The position of the requested local chunk coordinates.
- public IChunk GetChunkWithoutGeneration(Coordinates2D position)
- {
- // TODO: This could use some refactoring
- lock (Chunks)
- {
- if (!Chunks.ContainsKey(position))
- {
- if (regionFile != null)
- {
- // Search the stream for that region
- lock (regionFile)
- {
- var chunkData = GetChunkFromTable(position);
- if (chunkData == null)
- return null;
- regionFile.Seek(chunkData.Item1, SeekOrigin.Begin);
- /*int length = */new MinecraftStream(regionFile).ReadInt32(); // TODO: Avoid making new objects here, and in the WriteInt32
- int compressionMode = regionFile.ReadByte();
- switch (compressionMode)
- {
- case 1: // gzip
- break;
- case 2: // zlib
- var nbt = new NbtFile();
- nbt.LoadFromStream(regionFile, NbtCompression.ZLib, null);
- var chunk = Chunk.FromNbt(nbt);
- Chunks.Add(position, (IChunk)chunk);
+ Chunks.Add(position, chunk);
+ Console.WriteLine("Loaded chunk at {0}", chunk.Coordinates);
break;
default:
throw new InvalidDataException("Invalid compression scheme provided by region file.");
@@ -209,6 +163,7 @@ namespace TrueCraft.Core.World
var chunk = kvp.Value;
if (chunk.IsModified)
{
+ Console.WriteLine("Saving modified chunk at {0}", chunk.Coordinates);
var data = ((Chunk)chunk).ToNbt();
byte[] raw = data.SaveToBuffer(NbtCompression.ZLib);
diff --git a/TrueCraft.Core/World/World.cs b/TrueCraft.Core/World/World.cs
index 3549ee5..3048061 100644
--- a/TrueCraft.Core/World/World.cs
+++ b/TrueCraft.Core/World/World.cs
@@ -81,17 +81,6 @@ namespace TrueCraft.Core.World
region.GenerateChunk(new Coordinates2D(coordinates.X - regionX * 32, coordinates.Z - regionZ * 32));
}
- public Chunk GetChunkWithoutGeneration(Coordinates2D coordinates)
- {
- int regionX = coordinates.X / Region.Width - ((coordinates.X < 0) ? 1 : 0);
- int regionZ = coordinates.Z / Region.Depth - ((coordinates.Z < 0) ? 1 : 0);
-
- var regionPosition = new Coordinates2D(regionX, regionZ);
- if (!Regions.ContainsKey(regionPosition)) return null;
- return (Chunk)((Region)Regions[regionPosition]).GetChunkWithoutGeneration(
- new Coordinates2D(coordinates.X - regionX * 32, coordinates.Z - regionZ * 32));
- }
-
public void SetChunk(Coordinates2D coordinates, Chunk chunk)
{
int regionX = coordinates.X / Region.Width - ((coordinates.X < 0) ? 1 : 0);
diff --git a/TrueCraft/MultiplayerServer.cs b/TrueCraft/MultiplayerServer.cs
index b93bb6b..0e4646d 100644
--- a/TrueCraft/MultiplayerServer.cs
+++ b/TrueCraft/MultiplayerServer.cs
@@ -240,14 +240,8 @@ namespace TrueCraft
RemoteClient client;
lock (ClientLock)
client = Clients[i] as RemoteClient;
- var sendTimeout = DateTime.Now.AddMilliseconds(100);
while (client.PacketQueue.Count != 0)
{
- if (DateTime.Now > sendTimeout)
- {
- Console.WriteLine("Send timeout" + DateTime.Now);
- break;
- }
idle = false;
try
{
@@ -284,14 +278,8 @@ namespace TrueCraft
Clients.RemoveAt(i);
break;
}
- var receiveTimeout = DateTime.Now.AddMilliseconds(100);
while (client.DataAvailable)
{
- if (DateTime.Now > receiveTimeout)
- {
- Console.WriteLine("Receive timeout" + DateTime.Now);
- break;
- }
idle = false;
var packet = PacketReader.ReadPacket(client.MinecraftStream);
LogPacket(packet, true);
diff --git a/TrueCraft/Program.cs b/TrueCraft/Program.cs
index 6eccf90..4eb248f 100644
--- a/TrueCraft/Program.cs
+++ b/TrueCraft/Program.cs
@@ -10,6 +10,7 @@ using TrueCraft.API;
using TrueCraft.Core.Windows;
using System.IO;
using TrueCraft.Commands;
+using TrueCraft.API.World;
namespace TrueCraft
{
@@ -20,7 +21,19 @@ namespace TrueCraft
{
// TODO: Make this more flexible
var server = new MultiplayerServer();
- server.AddWorld(new World("default", new StandardGenerator()));
+ IWorld world;
+ try
+ {
+ // TODO: Save and load levels, with seeds and everything
+ world = World.LoadWorld("world");
+ world.ChunkProvider = new StandardGenerator();
+ }
+ catch
+ {
+ world = new World("default", new StandardGenerator());
+ world.Save("world");
+ }
+ server.AddWorld(world);
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));
@@ -29,7 +42,14 @@ namespace TrueCraft
server.ChatMessageReceived += HandleChatMessageReceived;
server.Start(new IPEndPoint(IPAddress.Any, 25565));
while (true)
- Thread.Sleep(1000);
+ {
+ Thread.Sleep(1000 * 30); // TODO: Allow users to customize world save interval
+ foreach (var w in server.Worlds)
+ {
+ server.Log(LogCategory.Debug, "Saved world '{0}'", w.Name);
+ w.Save();
+ }
+ }
}
static void HandleChatMessageReceived(object sender, ChatMessageEventArgs e)