Send initial slew of chunks to connected clients
This commit is contained in:
parent
05e132850c
commit
4d3d5ee8e0
10
TrueCraft.API/Entities/IEntity.cs
Normal file
10
TrueCraft.API/Entities/IEntity.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TrueCraft.API.Entities
|
||||||
|
{
|
||||||
|
public interface IEntity
|
||||||
|
{
|
||||||
|
int EntityID { get; set; }
|
||||||
|
Vector3 Position { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -25,5 +25,6 @@ namespace TrueCraft.API.Logging
|
|||||||
/// Generally useful information.
|
/// Generally useful information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Notice = 16,
|
Notice = 16,
|
||||||
|
All = Packets | Debug | Warning | Error | Notice
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,8 @@ namespace TrueCraft.API.Networking
|
|||||||
{
|
{
|
||||||
public interface IMinecraftStream
|
public interface IMinecraftStream
|
||||||
{
|
{
|
||||||
|
Stream BaseStream { get; }
|
||||||
|
|
||||||
byte ReadUInt8();
|
byte ReadUInt8();
|
||||||
sbyte ReadInt8();
|
sbyte ReadInt8();
|
||||||
void WriteUInt8(byte value);
|
void WriteUInt8(byte value);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
|
||||||
namespace TrueCraft.API.Networking
|
namespace TrueCraft.API.Networking
|
||||||
{
|
{
|
||||||
@ -6,6 +8,8 @@ namespace TrueCraft.API.Networking
|
|||||||
{
|
{
|
||||||
IMinecraftStream MinecraftStream { get; }
|
IMinecraftStream MinecraftStream { get; }
|
||||||
bool DataAvailable { get; }
|
bool DataAvailable { get; }
|
||||||
|
IWorld World { get; }
|
||||||
|
IEntity Entity { get; }
|
||||||
|
|
||||||
void QueuePacket(IPacket packet);
|
void QueuePacket(IPacket packet);
|
||||||
}
|
}
|
||||||
|
19
TrueCraft.API/Server/IEntityManager.cs
Normal file
19
TrueCraft.API/Server/IEntityManager.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
|
||||||
|
namespace TrueCraft.API.Server
|
||||||
|
{
|
||||||
|
public interface IEntityManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an entity to the world and assigns it an entity ID.
|
||||||
|
/// </summary>
|
||||||
|
void SpawnEntity(IEntity entity);
|
||||||
|
void DespawnEntity(IEntity entity);
|
||||||
|
IEntity GetEntityByID(int id);
|
||||||
|
void Update();
|
||||||
|
void SendEntitiesToClient(IRemoteClient client);
|
||||||
|
}
|
||||||
|
}
|
@ -25,5 +25,6 @@ namespace TrueCraft.API.Server
|
|||||||
void AddWorld(IWorld world);
|
void AddWorld(IWorld world);
|
||||||
void AddLogProvider(ILogProvider provider);
|
void AddLogProvider(ILogProvider provider);
|
||||||
void Log(LogCategory category, string text, params object[] parameters);
|
void Log(LogCategory category, string text, params object[] parameters);
|
||||||
|
IEntityManager GetEntityManagerForWorld(IWorld world);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,13 +56,14 @@
|
|||||||
<Compile Include="World\IWorld.cs" />
|
<Compile Include="World\IWorld.cs" />
|
||||||
<Compile Include="World\IChunk.cs" />
|
<Compile Include="World\IChunk.cs" />
|
||||||
<Compile Include="World\IChunkProvider.cs" />
|
<Compile Include="World\IChunkProvider.cs" />
|
||||||
<Compile Include="World\ISection.cs" />
|
|
||||||
<Compile Include="NibbleArray.cs" />
|
<Compile Include="NibbleArray.cs" />
|
||||||
<Compile Include="World\IRegion.cs" />
|
<Compile Include="World\IRegion.cs" />
|
||||||
<Compile Include="Biome.cs" />
|
<Compile Include="Biome.cs" />
|
||||||
<Compile Include="Logging\LogCategory.cs" />
|
<Compile Include="Logging\LogCategory.cs" />
|
||||||
<Compile Include="Logging\ILogProvider.cs" />
|
<Compile Include="Logging\ILogProvider.cs" />
|
||||||
<Compile Include="Server\IEventScheduler.cs" />
|
<Compile Include="Server\IEventScheduler.cs" />
|
||||||
|
<Compile Include="Server\IEntityManager.cs" />
|
||||||
|
<Compile Include="Entities\IEntity.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -70,6 +71,7 @@
|
|||||||
<Folder Include="Server\" />
|
<Folder Include="Server\" />
|
||||||
<Folder Include="World\" />
|
<Folder Include="World\" />
|
||||||
<Folder Include="Logging\" />
|
<Folder Include="Logging\" />
|
||||||
|
<Folder Include="Entities\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\externals\fNbt\fNbt\fNbt.csproj">
|
<ProjectReference Include="..\externals\fNbt\fNbt\fNbt.csproj">
|
||||||
|
@ -7,9 +7,12 @@ namespace TrueCraft.API.World
|
|||||||
Coordinates2D Coordinates { get; set; }
|
Coordinates2D Coordinates { get; set; }
|
||||||
bool IsModified { get; set; }
|
bool IsModified { get; set; }
|
||||||
int[] HeightMap { get; }
|
int[] HeightMap { get; }
|
||||||
ISection[] Sections { get; }
|
|
||||||
byte[] Biomes { get; }
|
byte[] Biomes { get; }
|
||||||
DateTime LastAccessed { get; set; }
|
DateTime LastAccessed { get; set; }
|
||||||
|
byte[] Blocks { get; }
|
||||||
|
NibbleArray Metadata { get; }
|
||||||
|
NibbleArray BlockLight { get; }
|
||||||
|
NibbleArray SkyLight { get; }
|
||||||
byte GetBlockID(Coordinates3D coordinates);
|
byte GetBlockID(Coordinates3D coordinates);
|
||||||
byte GetMetadata(Coordinates3D coordinates);
|
byte GetMetadata(Coordinates3D coordinates);
|
||||||
byte GetSkyLight(Coordinates3D coordinates);
|
byte GetSkyLight(Coordinates3D coordinates);
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace TrueCraft.API.World
|
|
||||||
{
|
|
||||||
public interface ISection
|
|
||||||
{
|
|
||||||
byte[] Blocks { get; }
|
|
||||||
NibbleArray Metadata { get; }
|
|
||||||
NibbleArray BlockLight { get; }
|
|
||||||
NibbleArray SkyLight { get; }
|
|
||||||
byte Y { get; }
|
|
||||||
byte GetBlockID(Coordinates3D coordinates);
|
|
||||||
byte GetMetadata(Coordinates3D coordinates);
|
|
||||||
byte GetSkyLight(Coordinates3D coordinates);
|
|
||||||
byte GetBlockLight(Coordinates3D coordinates);
|
|
||||||
void SetBlockID(Coordinates3D coordinates, byte value);
|
|
||||||
void SetMetadata(Coordinates3D coordinates, byte value);
|
|
||||||
void SetSkyLight(Coordinates3D coordinates, byte value);
|
|
||||||
void SetBlockLight(Coordinates3D coordinates, byte value);
|
|
||||||
void ProcessSection();
|
|
||||||
}
|
|
||||||
}
|
|
77
TrueCraft.Core/Networking/BufferedStream.cs
Normal file
77
TrueCraft.Core/Networking/BufferedStream.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace TrueCraft.Core.Networking
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Queues all writes until Stream.Flush() is called. This is different than System.IO.BufferedStream.
|
||||||
|
/// </summary>
|
||||||
|
public class BufferedStream : Stream
|
||||||
|
{
|
||||||
|
public BufferedStream(Stream baseStream)
|
||||||
|
{
|
||||||
|
BaseStream = baseStream;
|
||||||
|
PendingStream = new MemoryStream(512);
|
||||||
|
WriteImmediately = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream BaseStream { get; set; }
|
||||||
|
public MemoryStream PendingStream { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used by PacketReader to insert the ID and length into the stream before the packet contents.
|
||||||
|
/// </summary>
|
||||||
|
internal bool WriteImmediately { get; set; }
|
||||||
|
|
||||||
|
public override bool CanRead { get { return BaseStream.CanRead; } }
|
||||||
|
|
||||||
|
public override bool CanSeek { get { return BaseStream.CanSeek; } }
|
||||||
|
|
||||||
|
public override bool CanWrite { get { return BaseStream.CanWrite; } }
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
BaseStream.Write(PendingStream.GetBuffer(), 0, (int)PendingStream.Position);
|
||||||
|
PendingStream.Position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long PendingWrites
|
||||||
|
{
|
||||||
|
get { return PendingStream.Position; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Length
|
||||||
|
{
|
||||||
|
get { return BaseStream.Length; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get { return BaseStream.Position; }
|
||||||
|
set { BaseStream.Position = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return BaseStream.Read(buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
return BaseStream.Seek(offset, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
BaseStream.SetLength(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (WriteImmediately)
|
||||||
|
BaseStream.Write(buffer, offset, count);
|
||||||
|
else
|
||||||
|
PendingStream.Write(buffer, offset, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,13 +32,13 @@ namespace TrueCraft.Core.Networking
|
|||||||
RegisterPacketType<PlayerGroundedPacket>(serverbound: true, clientbound: false); // 0x0A
|
RegisterPacketType<PlayerGroundedPacket>(serverbound: true, clientbound: false); // 0x0A
|
||||||
RegisterPacketType<PlayerPositionPacket>(serverbound: true, clientbound: false); // 0x0B
|
RegisterPacketType<PlayerPositionPacket>(serverbound: true, clientbound: false); // 0x0B
|
||||||
RegisterPacketType<PlayerLookPacket>(serverbound: true, clientbound: false); // 0x0C
|
RegisterPacketType<PlayerLookPacket>(serverbound: true, clientbound: false); // 0x0C
|
||||||
RegisterPacketType<PlayerPositionPacket>(serverbound: true, clientbound: false); // 0x0D
|
RegisterPacketType<PlayerPositionAndLookPacket>(serverbound: true, clientbound: false); // 0x0D
|
||||||
RegisterPacketType<SetPlayerPositionPacket>(serverbound: false, clientbound: true); // 0x0D
|
RegisterPacketType<SetPlayerPositionPacket>(serverbound: false, clientbound: true); // 0x0D
|
||||||
RegisterPacketType<PlayerDiggingPacket>(serverbound: true, clientbound: false); // 0x0E
|
RegisterPacketType<PlayerDiggingPacket>(serverbound: true, clientbound: false); // 0x0E
|
||||||
RegisterPacketType<PlayerBlockPlacementPacket>(serverbound: true, clientbound: false); // 0x0F
|
RegisterPacketType<PlayerBlockPlacementPacket>(serverbound: true, clientbound: false); // 0x0F
|
||||||
RegisterPacketType<ChangeHeldItemPacket>(serverbound: true, clientbound: false); // 0x10
|
RegisterPacketType<ChangeHeldItemPacket>(serverbound: true, clientbound: false); // 0x10
|
||||||
RegisterPacketType<UseBedPacket>(serverbound: false, clientbound: true); // 0x11
|
RegisterPacketType<UseBedPacket>(serverbound: false, clientbound: true); // 0x11
|
||||||
RegisterPacketType<AnimationPacket>(serverbound: false, clientbound: true); // 0x12
|
RegisterPacketType<AnimationPacket>(); // 0x12
|
||||||
RegisterPacketType<PlayerActionPacket>(serverbound: true, clientbound: false); // 0x13
|
RegisterPacketType<PlayerActionPacket>(serverbound: true, clientbound: false); // 0x13
|
||||||
RegisterPacketType<SpawnPlayerPacket>(serverbound: false, clientbound: true); // 0x14
|
RegisterPacketType<SpawnPlayerPacket>(serverbound: false, clientbound: true); // 0x14
|
||||||
RegisterPacketType<SpawnItemPacket>(serverbound: false, clientbound: true); // 0x15
|
RegisterPacketType<SpawnItemPacket>(serverbound: false, clientbound: true); // 0x15
|
||||||
@ -114,6 +114,7 @@ namespace TrueCraft.Core.Networking
|
|||||||
{
|
{
|
||||||
stream.WriteUInt8(packet.ID);
|
stream.WriteUInt8(packet.ID);
|
||||||
packet.WritePacket(stream);
|
packet.WritePacket(stream);
|
||||||
|
stream.BaseStream.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,6 +12,11 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
{
|
{
|
||||||
public byte ID { get { return 0x03; } }
|
public byte ID { get { return 0x03; } }
|
||||||
|
|
||||||
|
public ChatMessagePacket(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
public string Message;
|
public string Message;
|
||||||
|
|
||||||
public void ReadPacket(IMinecraftStream stream)
|
public void ReadPacket(IMinecraftStream stream)
|
||||||
|
@ -10,6 +10,17 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
{
|
{
|
||||||
public byte ID { get { return 0x33; } }
|
public byte ID { get { return 0x33; } }
|
||||||
|
|
||||||
|
public ChunkDataPacket(int x, short y, int z, short width, short height, short depth, byte[] compressedData)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
Depth = depth;
|
||||||
|
CompressedData = compressedData;
|
||||||
|
}
|
||||||
|
|
||||||
public int X;
|
public int X;
|
||||||
public short Y;
|
public short Y;
|
||||||
public int Z;
|
public int Z;
|
||||||
|
@ -10,6 +10,13 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
{
|
{
|
||||||
public byte ID { get { return 0x32; } }
|
public byte ID { get { return 0x32; } }
|
||||||
|
|
||||||
|
public ChunkPreamblePacket(int x, int z, bool load = true)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Z = z;
|
||||||
|
Load = load;
|
||||||
|
}
|
||||||
|
|
||||||
public int X, Z;
|
public int X, Z;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If false, free the chunk. If true, allocate it.
|
/// If false, free the chunk. If true, allocate it.
|
||||||
|
@ -11,6 +11,17 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
{
|
{
|
||||||
public byte ID { get { return 0x0D; } }
|
public byte ID { get { return 0x0D; } }
|
||||||
|
|
||||||
|
public PlayerPositionAndLookPacket(double x, double y, double stance, double z, float yaw, float pitch, bool onGround)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
Stance = stance;
|
||||||
|
Yaw = yaw;
|
||||||
|
Pitch = pitch;
|
||||||
|
OnGround = onGround;
|
||||||
|
}
|
||||||
|
|
||||||
public double X, Y, Z;
|
public double X, Y, Z;
|
||||||
public double Stance;
|
public double Stance;
|
||||||
public float Yaw, Pitch;
|
public float Yaw, Pitch;
|
||||||
@ -33,8 +44,8 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
stream.WriteDouble(Y);
|
stream.WriteDouble(Y);
|
||||||
stream.WriteDouble(Stance);
|
stream.WriteDouble(Stance);
|
||||||
stream.WriteDouble(Z);
|
stream.WriteDouble(Z);
|
||||||
stream.WriteDouble(Yaw);
|
stream.WriteSingle(Yaw);
|
||||||
stream.WriteDouble(Pitch);
|
stream.WriteSingle(Pitch);
|
||||||
stream.WriteBoolean(OnGround);
|
stream.WriteBoolean(OnGround);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,17 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
{
|
{
|
||||||
public byte ID { get { return 0x0D; } }
|
public byte ID { get { return 0x0D; } }
|
||||||
|
|
||||||
|
public SetPlayerPositionPacket(double x, double y, double stance, double z, float yaw, float pitch, bool onGround)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
Stance = stance;
|
||||||
|
Yaw = yaw;
|
||||||
|
Pitch = pitch;
|
||||||
|
OnGround = onGround;
|
||||||
|
}
|
||||||
|
|
||||||
public double X, Y, Z;
|
public double X, Y, Z;
|
||||||
public double Stance;
|
public double Stance;
|
||||||
public float Yaw, Pitch;
|
public float Yaw, Pitch;
|
||||||
@ -32,8 +43,8 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
stream.WriteDouble(Stance);
|
stream.WriteDouble(Stance);
|
||||||
stream.WriteDouble(Y);
|
stream.WriteDouble(Y);
|
||||||
stream.WriteDouble(Z);
|
stream.WriteDouble(Z);
|
||||||
stream.WriteDouble(Yaw);
|
stream.WriteSingle(Yaw);
|
||||||
stream.WriteDouble(Pitch);
|
stream.WriteSingle(Pitch);
|
||||||
stream.WriteBoolean(OnGround);
|
stream.WriteBoolean(OnGround);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@
|
|||||||
<Compile Include="World\World.cs" />
|
<Compile Include="World\World.cs" />
|
||||||
<Compile Include="TerrainGen\FlatlandGenerator.cs" />
|
<Compile Include="TerrainGen\FlatlandGenerator.cs" />
|
||||||
<Compile Include="Logging\ConsoleLogProvider.cs" />
|
<Compile Include="Logging\ConsoleLogProvider.cs" />
|
||||||
|
<Compile Include="Networking\BufferedStream.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -12,25 +12,26 @@ namespace TrueCraft.Core.World
|
|||||||
{
|
{
|
||||||
public class Chunk : INbtSerializable, IChunk
|
public class Chunk : INbtSerializable, IChunk
|
||||||
{
|
{
|
||||||
public const int Width = 16, Height = 256, Depth = 16;
|
public const int Width = 16, Height = 128, Depth = 16;
|
||||||
|
|
||||||
private static readonly NbtSerializer Serializer = new NbtSerializer(typeof(Chunk));
|
private static readonly NbtSerializer Serializer = new NbtSerializer(typeof(Chunk));
|
||||||
|
|
||||||
[NbtIgnore]
|
[NbtIgnore]
|
||||||
public DateTime LastAccessed { get; set; }
|
public DateTime LastAccessed { get; set; }
|
||||||
|
|
||||||
public bool IsModified { get; set; }
|
|
||||||
|
|
||||||
public byte[] Biomes { get; set; }
|
|
||||||
|
|
||||||
public int[] HeightMap { get; set; }
|
|
||||||
|
|
||||||
[NbtIgnore]
|
[NbtIgnore]
|
||||||
public ISection[] Sections { get; set; }
|
public bool IsModified { get; set; }
|
||||||
|
[NbtIgnore]
|
||||||
|
public byte[] Blocks { get; set; }
|
||||||
|
[NbtIgnore]
|
||||||
|
public NibbleArray Metadata { get; set; }
|
||||||
|
[NbtIgnore]
|
||||||
|
public NibbleArray BlockLight { get; set; }
|
||||||
|
[NbtIgnore]
|
||||||
|
public NibbleArray SkyLight { get; set; }
|
||||||
|
public byte[] Biomes { get; set; }
|
||||||
|
public int[] HeightMap { get; set; }
|
||||||
[TagName("xPos")]
|
[TagName("xPos")]
|
||||||
public int X { get; set; }
|
public int X { get; set; }
|
||||||
|
|
||||||
[TagName("zPos")]
|
[TagName("zPos")]
|
||||||
public int Z { get; set; }
|
public int Z { get; set; }
|
||||||
|
|
||||||
@ -57,9 +58,6 @@ namespace TrueCraft.Core.World
|
|||||||
public Chunk()
|
public Chunk()
|
||||||
{
|
{
|
||||||
TerrainPopulated = true;
|
TerrainPopulated = true;
|
||||||
Sections = new Section[16];
|
|
||||||
for (int i = 0; i < Sections.Length; i++)
|
|
||||||
Sections[i] = new Section((byte)i);
|
|
||||||
Biomes = new byte[Width * Depth];
|
Biomes = new byte[Width * Depth];
|
||||||
HeightMap = new int[Width * Depth];
|
HeightMap = new int[Width * Depth];
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
@ -69,47 +67,49 @@ namespace TrueCraft.Core.World
|
|||||||
{
|
{
|
||||||
X = coordinates.X;
|
X = coordinates.X;
|
||||||
Z = coordinates.Z;
|
Z = coordinates.Z;
|
||||||
|
const int size = Width * Height * Depth;
|
||||||
|
Blocks = new byte[size];
|
||||||
|
Metadata = new NibbleArray(size);
|
||||||
|
BlockLight = new NibbleArray(size);
|
||||||
|
SkyLight = new NibbleArray(size);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
SkyLight[i] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetBlockID(Coordinates3D coordinates)
|
public byte GetBlockID(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
return Blocks[index];
|
||||||
return Sections[section].GetBlockID(coordinates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetMetadata(Coordinates3D coordinates)
|
public byte GetMetadata(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
return Metadata[index];
|
||||||
return Sections[section].GetMetadata(coordinates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetSkyLight(Coordinates3D coordinates)
|
public byte GetSkyLight(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
return SkyLight[index];
|
||||||
return Sections[section].GetSkyLight(coordinates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetBlockLight(Coordinates3D coordinates)
|
public byte GetBlockLight(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
return BlockLight[index];
|
||||||
return Sections[section].GetBlockLight(coordinates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlockID(Coordinates3D coordinates, byte value)
|
public void SetBlockID(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
Blocks[index] = value;
|
||||||
Sections[section].SetBlockID(coordinates, value);
|
|
||||||
var oldHeight = GetHeight((byte)coordinates.X, (byte)coordinates.Z);
|
var oldHeight = GetHeight((byte)coordinates.X, (byte)coordinates.Z);
|
||||||
if (value == 0) // Air
|
if (value == 0) // Air
|
||||||
{
|
{
|
||||||
@ -135,37 +135,24 @@ namespace TrueCraft.Core.World
|
|||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
Metadata[index] = value;
|
||||||
Sections[section].SetMetadata(coordinates, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSkyLight(Coordinates3D coordinates, byte value)
|
public void SetSkyLight(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
SkyLight[index] = value;
|
||||||
Sections[section].SetSkyLight(coordinates, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlockLight(Coordinates3D coordinates, byte value)
|
public void SetBlockLight(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
int section = GetSectionNumber(coordinates.Y);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width);
|
||||||
coordinates.Y = GetPositionInSection(coordinates.Y);
|
BlockLight[index] = value;
|
||||||
Sections[section].SetBlockLight(coordinates, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetSectionNumber(int yPos)
|
|
||||||
{
|
|
||||||
return yPos / 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetPositionInSection(int yPos)
|
|
||||||
{
|
|
||||||
return yPos % 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -206,19 +193,7 @@ namespace TrueCraft.Core.World
|
|||||||
var chunk = (NbtCompound)Serializer.Serialize(this, tagName, true);
|
var chunk = (NbtCompound)Serializer.Serialize(this, tagName, true);
|
||||||
var entities = new NbtList("Entities", NbtTagType.Compound);
|
var entities = new NbtList("Entities", NbtTagType.Compound);
|
||||||
chunk.Add(entities);
|
chunk.Add(entities);
|
||||||
var sections = new NbtList("Sections", NbtTagType.Compound);
|
// TODO: Save block data
|
||||||
var serializer = new NbtSerializer(typeof(Section));
|
|
||||||
for (int i = 0; i < Sections.Length; i++)
|
|
||||||
{
|
|
||||||
if (Sections[i] is Section)
|
|
||||||
{
|
|
||||||
if (!(Sections[i] as Section).IsAir)
|
|
||||||
sections.Add(serializer.Serialize(Sections[i]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sections.Add(serializer.Serialize(Sections[i]));
|
|
||||||
}
|
|
||||||
chunk.Add(sections);
|
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,18 +206,11 @@ namespace TrueCraft.Core.World
|
|||||||
this.Biomes = chunk.Biomes;
|
this.Biomes = chunk.Biomes;
|
||||||
this.HeightMap = chunk.HeightMap;
|
this.HeightMap = chunk.HeightMap;
|
||||||
this.LastUpdate = chunk.LastUpdate;
|
this.LastUpdate = chunk.LastUpdate;
|
||||||
this.Sections = chunk.Sections;
|
|
||||||
this.TerrainPopulated = chunk.TerrainPopulated;
|
this.TerrainPopulated = chunk.TerrainPopulated;
|
||||||
this.X = chunk.X;
|
this.X = chunk.X;
|
||||||
this.Z = chunk.Z;
|
this.Z = chunk.Z;
|
||||||
|
|
||||||
var serializer = new NbtSerializer(typeof(Section));
|
// TODO: Load block data
|
||||||
foreach (var section in compound["Sections"] as NbtList)
|
|
||||||
{
|
|
||||||
int index = section["Y"].IntValue;
|
|
||||||
Sections[index] = (Section)serializer.Deserialize(section);
|
|
||||||
Sections[index].ProcessSection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using TrueCraft.API.World;
|
|||||||
|
|
||||||
namespace TrueCraft.Core.World
|
namespace TrueCraft.Core.World
|
||||||
{
|
{
|
||||||
public class Section : ISection
|
public class Section
|
||||||
{
|
{
|
||||||
public const byte Width = 16, Height = 16, Depth = 16;
|
public const byte Width = 16, Height = 16, Depth = 16;
|
||||||
|
|
||||||
@ -42,31 +42,31 @@ namespace TrueCraft.Core.World
|
|||||||
|
|
||||||
public byte GetBlockID(Coordinates3D coordinates)
|
public byte GetBlockID(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
return Blocks[index];
|
return Blocks[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetMetadata(Coordinates3D coordinates)
|
public byte GetMetadata(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
return Metadata[index];
|
return Metadata[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetSkyLight(Coordinates3D coordinates)
|
public byte GetSkyLight(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
return SkyLight[index];
|
return SkyLight[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetBlockLight(Coordinates3D coordinates)
|
public byte GetBlockLight(Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
return BlockLight[index];
|
return BlockLight[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlockID(Coordinates3D coordinates, byte value)
|
public void SetBlockID(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
{
|
{
|
||||||
if (Blocks[index] != 0)
|
if (Blocks[index] != 0)
|
||||||
@ -82,19 +82,19 @@ namespace TrueCraft.Core.World
|
|||||||
|
|
||||||
public void SetMetadata(Coordinates3D coordinates, byte value)
|
public void SetMetadata(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
Metadata[index] = value;
|
Metadata[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSkyLight(Coordinates3D coordinates, byte value)
|
public void SetSkyLight(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
SkyLight[index] = value;
|
SkyLight[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlockLight(Coordinates3D coordinates, byte value)
|
public void SetBlockLight(Coordinates3D coordinates, byte value)
|
||||||
{
|
{
|
||||||
int index = coordinates.X + (coordinates.Z * Width) + (coordinates.Y * Height * Width);
|
int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Depth * Width);
|
||||||
BlockLight[index] = value;
|
BlockLight[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
TrueCraft/Entities/PlayerEntity.cs
Normal file
16
TrueCraft/Entities/PlayerEntity.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using TrueCraft.API;
|
||||||
|
|
||||||
|
namespace TrueCraft.Entities
|
||||||
|
{
|
||||||
|
public class PlayerEntity : IEntity
|
||||||
|
{
|
||||||
|
public PlayerEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int EntityID { get; set; }
|
||||||
|
public Vector3 Position { get; set; }
|
||||||
|
}
|
||||||
|
}
|
48
TrueCraft/EntityManager.cs
Normal file
48
TrueCraft/EntityManager.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
|
||||||
|
namespace TrueCraft
|
||||||
|
{
|
||||||
|
public class EntityManager : IEntityManager
|
||||||
|
{
|
||||||
|
public IWorld World { get; set; }
|
||||||
|
public IMultiplayerServer Server { get; set; }
|
||||||
|
|
||||||
|
private int NextEntityID { get; set; }
|
||||||
|
|
||||||
|
public EntityManager(IMultiplayerServer server, IWorld world)
|
||||||
|
{
|
||||||
|
Server = server;
|
||||||
|
World = world;
|
||||||
|
NextEntityID = 1; // TODO: Handle loading worlds that already have entities
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SpawnEntity(IEntity entity)
|
||||||
|
{
|
||||||
|
entity.EntityID = NextEntityID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DespawnEntity(IEntity entity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEntity GetEntityByID(int id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendEntitiesToClient(IRemoteClient client)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ using TrueCraft.API.Server;
|
|||||||
using TrueCraft.API.Networking;
|
using TrueCraft.API.Networking;
|
||||||
using TrueCraft.Core.Networking.Packets;
|
using TrueCraft.Core.Networking.Packets;
|
||||||
using TrueCraft.API.Logging;
|
using TrueCraft.API.Logging;
|
||||||
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.Entities;
|
||||||
|
|
||||||
namespace TrueCraft.Handlers
|
namespace TrueCraft.Handlers
|
||||||
{
|
{
|
||||||
@ -21,16 +23,24 @@ namespace TrueCraft.Handlers
|
|||||||
var packet = (LoginRequestPacket)_packet;
|
var packet = (LoginRequestPacket)_packet;
|
||||||
var client = (RemoteClient)_client;
|
var client = (RemoteClient)_client;
|
||||||
if (packet.ProtocolVersion < server.PacketReader.ProtocolVersion)
|
if (packet.ProtocolVersion < server.PacketReader.ProtocolVersion)
|
||||||
client.QueuePacket(new DisconnectPacket("Client outdated! Use beta 1.7.3!"));
|
client.QueuePacket(new DisconnectPacket("Client outdated! Use beta 1.7.3."));
|
||||||
else if (packet.ProtocolVersion > server.PacketReader.ProtocolVersion)
|
else if (packet.ProtocolVersion > server.PacketReader.ProtocolVersion)
|
||||||
client.QueuePacket(new DisconnectPacket("Server outdated! Use beta 1.7.3!"));
|
client.QueuePacket(new DisconnectPacket("Server outdated! Use beta 1.7.3."));
|
||||||
else if (server.Worlds.Count == 0)
|
else if (server.Worlds.Count == 0)
|
||||||
client.QueuePacket(new DisconnectPacket("Server has no worlds configured."));
|
client.QueuePacket(new DisconnectPacket("Server has no worlds configured."));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
server.Log(LogCategory.Notice, "{0} joined the server.", client.Username);
|
server.Log(LogCategory.Notice, "{0} joined the server.", client.Username); // TODO: Mention the same thing in chat
|
||||||
client.LoggedIn = true;
|
client.LoggedIn = true;
|
||||||
server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(3), (s) => client.QueuePacket(new DisconnectPacket("Bye!")));
|
client.Entity = new PlayerEntity();
|
||||||
|
client.World = server.Worlds[0];
|
||||||
|
server.GetEntityManagerForWorld(client.World).SpawnEntity(client.Entity);
|
||||||
|
client.QueuePacket(new LoginResponsePacket(0, 0, Dimension.Overworld));
|
||||||
|
client.ChunkRadius = 4;
|
||||||
|
client.UpdateChunks();
|
||||||
|
client.QueuePacket(new SpawnPositionPacket(0, 16, 0));
|
||||||
|
client.QueuePacket(new SetPlayerPositionPacket(0, 16, 17, 0, 0, 0, true));
|
||||||
|
client.QueuePacket(new ChatMessagePacket(string.Format("Welcome to the server, {0}!", client.Username)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace TrueCraft
|
|||||||
public IPacketReader PacketReader { get; private set; }
|
public IPacketReader PacketReader { get; private set; }
|
||||||
public IList<IRemoteClient> Clients { get; private set; }
|
public IList<IRemoteClient> Clients { get; private set; }
|
||||||
public IList<IWorld> Worlds { get; private set; }
|
public IList<IWorld> Worlds { get; private set; }
|
||||||
|
public IList<IEntityManager> EntityManagers { get; private set; }
|
||||||
public IEventScheduler Scheduler { get; private set; }
|
public IEventScheduler Scheduler { get; private set; }
|
||||||
|
|
||||||
private Timer NetworkWorker, EnvironmentWorker;
|
private Timer NetworkWorker, EnvironmentWorker;
|
||||||
@ -33,6 +34,7 @@ namespace TrueCraft
|
|||||||
EnvironmentWorker = new Timer(DoEnvironment);
|
EnvironmentWorker = new Timer(DoEnvironment);
|
||||||
PacketHandlers = new PacketHandler[0x100];
|
PacketHandlers = new PacketHandler[0x100];
|
||||||
Worlds = new List<IWorld>();
|
Worlds = new List<IWorld>();
|
||||||
|
EntityManagers = new List<IEntityManager>();
|
||||||
LogProviders = new List<ILogProvider>();
|
LogProviders = new List<ILogProvider>();
|
||||||
Scheduler = new EventScheduler(this);
|
Scheduler = new EventScheduler(this);
|
||||||
|
|
||||||
@ -58,6 +60,8 @@ namespace TrueCraft
|
|||||||
public void AddWorld(IWorld world)
|
public void AddWorld(IWorld world)
|
||||||
{
|
{
|
||||||
Worlds.Add(world);
|
Worlds.Add(world);
|
||||||
|
var manager = new EntityManager(this, world);
|
||||||
|
EntityManagers.Add(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddLogProvider(ILogProvider provider)
|
public void AddLogProvider(ILogProvider provider)
|
||||||
@ -74,6 +78,17 @@ namespace TrueCraft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEntityManager GetEntityManagerForWorld(IWorld world)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < EntityManagers.Count; i++)
|
||||||
|
{
|
||||||
|
var manager = EntityManagers[i] as EntityManager;
|
||||||
|
if (manager.World == world)
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void DisconnectClient(IRemoteClient _client)
|
private void DisconnectClient(IRemoteClient _client)
|
||||||
{
|
{
|
||||||
var client = (RemoteClient)_client;
|
var client = (RemoteClient)_client;
|
||||||
@ -85,7 +100,7 @@ namespace TrueCraft
|
|||||||
private void AcceptClient(IAsyncResult result)
|
private void AcceptClient(IAsyncResult result)
|
||||||
{
|
{
|
||||||
var tcpClient = Listener.EndAcceptTcpClient(result);
|
var tcpClient = Listener.EndAcceptTcpClient(result);
|
||||||
var client = new RemoteClient(tcpClient.GetStream());
|
var client = new RemoteClient(this, tcpClient.GetStream());
|
||||||
Clients.Add(client);
|
Clients.Add(client);
|
||||||
Listener.BeginAcceptTcpClient(AcceptClient, null);
|
Listener.BeginAcceptTcpClient(AcceptClient, null);
|
||||||
}
|
}
|
||||||
@ -105,6 +120,7 @@ namespace TrueCraft
|
|||||||
IPacket packet;
|
IPacket packet;
|
||||||
while (!client.PacketQueue.TryDequeue(out packet)) { }
|
while (!client.PacketQueue.TryDequeue(out packet)) { }
|
||||||
PacketReader.WritePacket(client.MinecraftStream, packet);
|
PacketReader.WritePacket(client.MinecraftStream, packet);
|
||||||
|
Console.WriteLine("Sent {0}", packet.GetType().Name);
|
||||||
if (packet is DisconnectPacket)
|
if (packet is DisconnectPacket)
|
||||||
{
|
{
|
||||||
DisconnectClient(client);
|
DisconnectClient(client);
|
||||||
@ -114,6 +130,7 @@ namespace TrueCraft
|
|||||||
if (client.DataAvailable)
|
if (client.DataAvailable)
|
||||||
{
|
{
|
||||||
var packet = PacketReader.ReadPacket(client.MinecraftStream);
|
var packet = PacketReader.ReadPacket(client.MinecraftStream);
|
||||||
|
Console.WriteLine("Got {0}", packet.GetType().Name);
|
||||||
if (PacketHandlers[packet.ID] != null)
|
if (PacketHandlers[packet.ID] != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -4,6 +4,7 @@ using System.Threading;
|
|||||||
using TrueCraft.Core.World;
|
using TrueCraft.Core.World;
|
||||||
using TrueCraft.Core.TerrainGen;
|
using TrueCraft.Core.TerrainGen;
|
||||||
using TrueCraft.Core.Logging;
|
using TrueCraft.Core.Logging;
|
||||||
|
using TrueCraft.API.Logging;
|
||||||
|
|
||||||
namespace TrueCraft
|
namespace TrueCraft
|
||||||
{
|
{
|
||||||
@ -14,7 +15,7 @@ namespace TrueCraft
|
|||||||
// TODO: Make this more flexible
|
// TODO: Make this more flexible
|
||||||
var server = new MultiplayerServer();
|
var server = new MultiplayerServer();
|
||||||
server.AddWorld(new World("default", new FlatlandGenerator()));
|
server.AddWorld(new World("default", new FlatlandGenerator()));
|
||||||
server.AddLogProvider(new ConsoleLogProvider());
|
server.AddLogProvider(new ConsoleLogProvider(LogCategory.All));
|
||||||
server.Start(new IPEndPoint(IPAddress.Any, 25565));
|
server.Start(new IPEndPoint(IPAddress.Any, 25565));
|
||||||
while (true)
|
while (true)
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
@ -3,16 +3,27 @@ using TrueCraft.API.Networking;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using TrueCraft.Core.Networking;
|
using TrueCraft.Core.Networking;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using TrueCraft.API;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using TrueCraft.Core.Networking.Packets;
|
||||||
|
using TrueCraft.Core.World;
|
||||||
|
using Ionic.Zlib;
|
||||||
|
|
||||||
namespace TrueCraft
|
namespace TrueCraft
|
||||||
{
|
{
|
||||||
public class RemoteClient : IRemoteClient
|
public class RemoteClient : IRemoteClient
|
||||||
{
|
{
|
||||||
public RemoteClient(NetworkStream stream)
|
public RemoteClient(IMultiplayerServer server, NetworkStream stream)
|
||||||
{
|
{
|
||||||
NetworkStream = stream;
|
NetworkStream = stream;
|
||||||
MinecraftStream = new MinecraftStream(NetworkStream);
|
MinecraftStream = new MinecraftStream(new BufferedStream(NetworkStream));
|
||||||
PacketQueue = new ConcurrentQueue<IPacket>();
|
PacketQueue = new ConcurrentQueue<IPacket>();
|
||||||
|
LoadedChunks = new List<Coordinates2D>();
|
||||||
|
Server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkStream NetworkStream { get; set; }
|
public NetworkStream NetworkStream { get; set; }
|
||||||
@ -20,6 +31,12 @@ namespace TrueCraft
|
|||||||
public ConcurrentQueue<IPacket> PacketQueue { get; private set; }
|
public ConcurrentQueue<IPacket> PacketQueue { get; private set; }
|
||||||
public string Username { get; internal set; }
|
public string Username { get; internal set; }
|
||||||
public bool LoggedIn { get; internal set; }
|
public bool LoggedIn { get; internal set; }
|
||||||
|
public IMultiplayerServer Server { get; set; }
|
||||||
|
public IWorld World { get; internal set; }
|
||||||
|
public IEntity Entity { get; internal set; }
|
||||||
|
|
||||||
|
internal int ChunkRadius { get; set; }
|
||||||
|
internal IList<Coordinates2D> LoadedChunks { get; set; }
|
||||||
|
|
||||||
public bool DataAvailable
|
public bool DataAvailable
|
||||||
{
|
{
|
||||||
@ -33,5 +50,81 @@ namespace TrueCraft
|
|||||||
{
|
{
|
||||||
PacketQueue.Enqueue(packet);
|
PacketQueue.Enqueue(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void UpdateChunks()
|
||||||
|
{
|
||||||
|
var newChunks = new List<Coordinates2D>();
|
||||||
|
for (int x = -ChunkRadius; x < ChunkRadius; x++)
|
||||||
|
{
|
||||||
|
for (int z = -ChunkRadius; z < ChunkRadius; z++)
|
||||||
|
{
|
||||||
|
newChunks.Add(new Coordinates2D(
|
||||||
|
((int)Entity.Position.X >> 4) + x,
|
||||||
|
((int)Entity.Position.Z >> 4) + z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Unload extraneous columns
|
||||||
|
lock (LoadedChunks)
|
||||||
|
{
|
||||||
|
var currentChunks = new List<Coordinates2D>(LoadedChunks);
|
||||||
|
foreach (Coordinates2D chunk in currentChunks)
|
||||||
|
{
|
||||||
|
if (!newChunks.Contains(chunk))
|
||||||
|
UnloadChunk(chunk);
|
||||||
|
}
|
||||||
|
// Load new columns
|
||||||
|
foreach (Coordinates2D chunk in newChunks)
|
||||||
|
{
|
||||||
|
if (!LoadedChunks.Contains(chunk))
|
||||||
|
LoadChunk(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UnloadAllChunks()
|
||||||
|
{
|
||||||
|
lock (LoadedChunks)
|
||||||
|
{
|
||||||
|
while (LoadedChunks.Any())
|
||||||
|
{
|
||||||
|
UnloadChunk(LoadedChunks[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void LoadChunk(Coordinates2D position)
|
||||||
|
{
|
||||||
|
var chunk = World.GetChunk(position);
|
||||||
|
QueuePacket(new ChunkPreamblePacket(chunk.Coordinates.X, chunk.Coordinates.Z));
|
||||||
|
QueuePacket(CreatePacket(chunk));
|
||||||
|
LoadedChunks.Add(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UnloadChunk(Coordinates2D position)
|
||||||
|
{
|
||||||
|
QueuePacket(new ChunkPreamblePacket(position.X, position.Z, false));
|
||||||
|
LoadedChunks.Remove(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChunkDataPacket CreatePacket(IChunk chunk)
|
||||||
|
{
|
||||||
|
// TODO: Be smarter about this
|
||||||
|
var X = chunk.Coordinates.X;
|
||||||
|
var Z = chunk.Coordinates.Z;
|
||||||
|
|
||||||
|
const int blocksPerChunk = Chunk.Width * Chunk.Height * Chunk.Depth;
|
||||||
|
const int bytesPerChunk = (int)(blocksPerChunk * 2.5);
|
||||||
|
|
||||||
|
byte[] data = new byte[bytesPerChunk];
|
||||||
|
|
||||||
|
Array.Copy(chunk.Blocks, 0, data, 0, chunk.Blocks.Length);
|
||||||
|
Array.Copy(chunk.Metadata.Data, 0, data, chunk.Blocks.Length, chunk.Metadata.Data.Length);
|
||||||
|
Array.Copy(chunk.BlockLight.Data, 0, data, chunk.Blocks.Length + chunk.Metadata.Data.Length, chunk.BlockLight.Data.Length);
|
||||||
|
Array.Copy(chunk.SkyLight.Data, 0, data, chunk.Blocks.Length + chunk.Metadata.Data.Length
|
||||||
|
+ chunk.BlockLight.Data.Length, chunk.SkyLight.Data.Length);
|
||||||
|
|
||||||
|
var result = ZlibStream.CompressBuffer(data);
|
||||||
|
return new ChunkDataPacket(X * Chunk.Width, 0, Z * Chunk.Depth, Chunk.Width, Chunk.Height, Chunk.Depth, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,6 +30,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="Ionic.Zip.Reduced">
|
||||||
|
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
@ -39,6 +42,8 @@
|
|||||||
<Compile Include="Handlers\PacketHandlers.cs" />
|
<Compile Include="Handlers\PacketHandlers.cs" />
|
||||||
<Compile Include="Handlers\LoginHandlers.cs" />
|
<Compile Include="Handlers\LoginHandlers.cs" />
|
||||||
<Compile Include="EventScheduler.cs" />
|
<Compile Include="EventScheduler.cs" />
|
||||||
|
<Compile Include="EntityManager.cs" />
|
||||||
|
<Compile Include="Entities\PlayerEntity.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -50,8 +55,13 @@
|
|||||||
<Project>{FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}</Project>
|
<Project>{FA4BE9A3-DBF0-4380-BA2B-FFAA71C4706D}</Project>
|
||||||
<Name>TrueCraft.Core</Name>
|
<Name>TrueCraft.Core</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\externals\fNbt\fNbt\fNbt.csproj">
|
||||||
|
<Project>{4488498D-976D-4DA3-BF72-109531AF0488}</Project>
|
||||||
|
<Name>fNbt</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Handlers\" />
|
<Folder Include="Handlers\" />
|
||||||
|
<Folder Include="Entities\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,3 +1,3 @@
|
|||||||
Differences between TrueCraft and vanilla beta 1.7.3:
|
Differences between TrueCraft and vanilla beta 1.7.3:
|
||||||
|
|
||||||
- Uses the Anvil level format instead of MCRegion
|
- Uses a modified form of the Anvil level format instead of MCRegion
|
||||||
|
Reference in New Issue
Block a user