Fix merge conflict
This commit is contained in:
commit
2dd36b28ec
44
TrueCraft.Client/Rendering/Blocks/FarmlandRenderer.cs
Normal file
44
TrueCraft.Client/Rendering/Blocks/FarmlandRenderer.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
|
namespace TrueCraft.Client.Rendering.Blocks
|
||||||
|
{
|
||||||
|
public class FarmlandRenderer : BlockRenderer
|
||||||
|
{
|
||||||
|
static FarmlandRenderer()
|
||||||
|
{
|
||||||
|
BlockRenderer.RegisterRenderer(FarmlandBlock.BlockID, new FarmlandRenderer());
|
||||||
|
for (int i = 0; i < Texture.Length; i++)
|
||||||
|
Texture[i] *= new Vector2(16f / 256f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 TextureMap = new Vector2(7, 5);
|
||||||
|
private static Vector2[] Texture =
|
||||||
|
{
|
||||||
|
TextureMap + Vector2.UnitX + Vector2.UnitY,
|
||||||
|
TextureMap + Vector2.UnitY,
|
||||||
|
TextureMap,
|
||||||
|
TextureMap + Vector2.UnitX,
|
||||||
|
};
|
||||||
|
|
||||||
|
public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset,
|
||||||
|
Tuple<int, int> textureMap, int indiciesOffset, out int[] indicies)
|
||||||
|
{
|
||||||
|
var overhead = new Vector3(0.5f, 0.5f, 0.5f);
|
||||||
|
var cube = CreateUniformCube(overhead, Texture, indiciesOffset, out indicies, Color.White);
|
||||||
|
for (int i = 0; i < cube.Length; i++)
|
||||||
|
{
|
||||||
|
if (cube[i].Position.Y > 0)
|
||||||
|
{
|
||||||
|
cube[i].Position.Y *= 15f / 16f;
|
||||||
|
}
|
||||||
|
cube[i].Position += offset;
|
||||||
|
cube[i].Position -= overhead;
|
||||||
|
}
|
||||||
|
return cube;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
TrueCraft.Client/Rendering/Blocks/WaterRenderer.cs
Normal file
46
TrueCraft.Client/Rendering/Blocks/WaterRenderer.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
|
namespace TrueCraft.Client.Rendering.Blocks
|
||||||
|
{
|
||||||
|
public class WaterRenderer : BlockRenderer
|
||||||
|
{
|
||||||
|
static WaterRenderer()
|
||||||
|
{
|
||||||
|
BlockRenderer.RegisterRenderer(WaterBlock.BlockID, new WaterRenderer());
|
||||||
|
BlockRenderer.RegisterRenderer(StationaryWaterBlock.BlockID, new WaterRenderer());
|
||||||
|
for (int i = 0; i < Texture.Length; i++)
|
||||||
|
Texture[i] *= new Vector2(16f / 256f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 TextureMap = new Vector2(13, 12);
|
||||||
|
private static Vector2[] Texture =
|
||||||
|
{
|
||||||
|
TextureMap + Vector2.UnitX + Vector2.UnitY,
|
||||||
|
TextureMap + Vector2.UnitY,
|
||||||
|
TextureMap,
|
||||||
|
TextureMap + Vector2.UnitX,
|
||||||
|
};
|
||||||
|
|
||||||
|
public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset,
|
||||||
|
Tuple<int, int> textureMap, int indiciesOffset, out int[] indicies)
|
||||||
|
{
|
||||||
|
// TODO: Rest of water rendering (shape and level and so on)
|
||||||
|
var overhead = new Vector3(0.5f, 0.5f, 0.5f);
|
||||||
|
var cube = CreateUniformCube(overhead, Texture, indiciesOffset, out indicies, Color.White);
|
||||||
|
for (int i = 0; i < cube.Length; i++)
|
||||||
|
{
|
||||||
|
if (cube[i].Position.Y > 0)
|
||||||
|
{
|
||||||
|
cube[i].Position.Y *= 15f / 16f;
|
||||||
|
}
|
||||||
|
cube[i].Position += offset;
|
||||||
|
cube[i].Position -= overhead;
|
||||||
|
}
|
||||||
|
return cube;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs
Normal file
105
TrueCraft.Client/Rendering/Blocks/WheatRenderer.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
|
|
||||||
|
namespace TrueCraft.Client.Rendering
|
||||||
|
{
|
||||||
|
public class WheatRenderer : BlockRenderer
|
||||||
|
{
|
||||||
|
static WheatRenderer()
|
||||||
|
{
|
||||||
|
BlockRenderer.RegisterRenderer(CropsBlock.BlockID, new WheatRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2[][] Textures;
|
||||||
|
|
||||||
|
public WheatRenderer()
|
||||||
|
{
|
||||||
|
var textureMap = new Vector2(8, 5);
|
||||||
|
Textures = new Vector2[8][];
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
Textures[i] = new[]
|
||||||
|
{
|
||||||
|
textureMap + Vector2.UnitX + Vector2.UnitY,
|
||||||
|
textureMap + Vector2.UnitY,
|
||||||
|
textureMap,
|
||||||
|
textureMap + Vector2.UnitX,
|
||||||
|
};
|
||||||
|
for (int j = 0; j < Textures[i].Length; j++)
|
||||||
|
Textures[i][j] *= new Vector2(16f / 256f);
|
||||||
|
textureMap += new Vector2(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset,
|
||||||
|
Tuple<int, int> textureMap, int indiciesOffset, out int[] indicies)
|
||||||
|
{
|
||||||
|
// Wheat is rendered by rendering the four vertical faces of a cube, then moving them
|
||||||
|
// towards the middle. We also render a second set of four faces so that you can see
|
||||||
|
// each face from the opposite side (to avoid culling)
|
||||||
|
var texture = Textures[0];
|
||||||
|
if (descriptor.Metadata < Textures.Length)
|
||||||
|
texture = Textures[descriptor.Metadata];
|
||||||
|
indicies = new int[4 * 2 * 6];
|
||||||
|
var verticies = new VertexPositionNormalColorTexture[4 * 2 * 6];
|
||||||
|
int[] _indicies;
|
||||||
|
for (int _side = 0; _side < 4; _side++) // Y faces are the last two in the CubeFace enum, so we can just iterate to 4
|
||||||
|
{
|
||||||
|
var side = (CubeFace)_side;
|
||||||
|
var quad = CreateQuad(side, Vector3.Zero, texture, 0, indiciesOffset, out _indicies, Color.White);
|
||||||
|
if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < quad.Length; i++)
|
||||||
|
{
|
||||||
|
quad[i].Position.X *= 0.5f;
|
||||||
|
quad[i].Position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < quad.Length; i++)
|
||||||
|
{
|
||||||
|
quad[i].Position.Z *= 0.5f;
|
||||||
|
quad[i].Position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array.Copy(quad, 0, verticies, _side * 4, 4);
|
||||||
|
Array.Copy(_indicies, 0, indicies, _side * 6, 6);
|
||||||
|
}
|
||||||
|
indiciesOffset += 4 * 6;
|
||||||
|
for (int _side = 0; _side < 4; _side++)
|
||||||
|
{
|
||||||
|
var side = (CubeFace)_side;
|
||||||
|
var quad = CreateQuad(side, Vector3.Zero, texture, 0, indiciesOffset, out _indicies, Color.White);
|
||||||
|
if (side == CubeFace.NegativeX || side == CubeFace.PositiveX)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < quad.Length; i++)
|
||||||
|
{
|
||||||
|
quad[i].Position.X *= 0.5f;
|
||||||
|
quad[i].Position.X = -quad[i].Position.X;
|
||||||
|
quad[i].Position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < quad.Length; i++)
|
||||||
|
{
|
||||||
|
quad[i].Position.Z *= 0.5f;
|
||||||
|
quad[i].Position.Z = -quad[i].Position.Z;
|
||||||
|
quad[i].Position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array.Copy(quad, 0, verticies, _side * 4 + 4 * 4, 4);
|
||||||
|
Array.Copy(_indicies, 0, indicies, _side * 6 + 6 * 4, 6);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < verticies.Length; i++)
|
||||||
|
{
|
||||||
|
verticies[i].Position.Y -= 1 / 16f;
|
||||||
|
}
|
||||||
|
return verticies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -102,6 +102,8 @@
|
|||||||
<Compile Include="Rendering\Blocks\VegitationRenderer.cs" />
|
<Compile Include="Rendering\Blocks\VegitationRenderer.cs" />
|
||||||
<Compile Include="Rendering\VertexPositionNormalColorTexture.cs" />
|
<Compile Include="Rendering\VertexPositionNormalColorTexture.cs" />
|
||||||
<Compile Include="Rendering\Blocks\WheatRenderer.cs" />
|
<Compile Include="Rendering\Blocks\WheatRenderer.cs" />
|
||||||
|
<Compile Include="Rendering\Blocks\WaterRenderer.cs" />
|
||||||
|
<Compile Include="Rendering\Blocks\FarmlandRenderer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -78,7 +78,7 @@ namespace TrueCraft.Client
|
|||||||
base.Initialize(); // (calls LoadContent)
|
base.Initialize(); // (calls LoadContent)
|
||||||
ChunkConverter = new ChunkRenderer(this, Client.World.World.BlockRepository);
|
ChunkConverter = new ChunkRenderer(this, Client.World.World.BlockRepository);
|
||||||
Client.ChunkLoaded += (sender, e) => ChunkConverter.Enqueue(e.Chunk);
|
Client.ChunkLoaded += (sender, e) => ChunkConverter.Enqueue(e.Chunk);
|
||||||
Client.ChunkModified += (sender, e) => ChunkConverter.Enqueue(e.Chunk, true);
|
//Client.ChunkModified += (sender, e) => ChunkConverter.Enqueue(e.Chunk, true);
|
||||||
ChunkConverter.MeshCompleted += ChunkConverter_MeshGenerated;
|
ChunkConverter.MeshCompleted += ChunkConverter_MeshGenerated;
|
||||||
ChunkConverter.Start();
|
ChunkConverter.Start();
|
||||||
Client.PropertyChanged += HandleClientPropertyChanged;
|
Client.PropertyChanged += HandleClientPropertyChanged;
|
||||||
|
@ -24,6 +24,8 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
|
|
||||||
public override string DisplayName { get { return "Crops"; } }
|
public override string DisplayName { get { return "Crops"; } }
|
||||||
|
|
||||||
|
public override TrueCraft.API.BoundingBox? BoundingBox { get { return null; } }
|
||||||
|
|
||||||
public override Tuple<int, int> GetTextureMap(byte metadata)
|
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||||
{
|
{
|
||||||
return new Tuple<int, int>(8, 5);
|
return new Tuple<int, int>(8, 5);
|
||||||
@ -66,4 +68,4 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
(server) => GrowBlock(server, world, descriptor.Coordinates + MathHelper.BlockFaceToCoordinates(face)));
|
(server) => GrowBlock(server, world, descriptor.Coordinates + MathHelper.BlockFaceToCoordinates(face)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,8 @@ namespace TrueCraft
|
|||||||
private readonly PacketHandler[] PacketHandlers;
|
private readonly PacketHandler[] PacketHandlers;
|
||||||
private IList<ILogProvider> LogProviders;
|
private IList<ILogProvider> LogProviders;
|
||||||
internal object ClientLock = new object();
|
internal object ClientLock = new object();
|
||||||
|
|
||||||
|
private QueryProtocol QueryProtocol;
|
||||||
|
|
||||||
public bool ShuttingDown { get; private set; }
|
public bool ShuttingDown { get; private set; }
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ namespace TrueCraft
|
|||||||
CraftingRepository = craftingRepository;
|
CraftingRepository = craftingRepository;
|
||||||
PendingBlockUpdates = new Queue<BlockUpdate>();
|
PendingBlockUpdates = new Queue<BlockUpdate>();
|
||||||
EnableClientLogging = false;
|
EnableClientLogging = false;
|
||||||
|
QueryProtocol = new TrueCraft.QueryProtocol(this);
|
||||||
|
|
||||||
AccessConfiguration = Configuration.LoadConfiguration<AccessConfiguration>("access.yaml");
|
AccessConfiguration = Configuration.LoadConfiguration<AccessConfiguration>("access.yaml");
|
||||||
|
|
||||||
@ -118,12 +121,16 @@ namespace TrueCraft
|
|||||||
|
|
||||||
Log(LogCategory.Notice, "Running TrueCraft server on {0}", EndPoint);
|
Log(LogCategory.Notice, "Running TrueCraft server on {0}", EndPoint);
|
||||||
EnvironmentWorker.Change(100, 1000 / 20);
|
EnvironmentWorker.Change(100, 1000 / 20);
|
||||||
|
if(Program.ServerConfiguration.Query)
|
||||||
|
QueryProtocol.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
ShuttingDown = true;
|
ShuttingDown = true;
|
||||||
Listener.Stop();
|
Listener.Stop();
|
||||||
|
if(Program.ServerConfiguration.Query)
|
||||||
|
QueryProtocol.Stop();
|
||||||
foreach (var w in Worlds)
|
foreach (var w in Worlds)
|
||||||
w.Save();
|
w.Save();
|
||||||
foreach (var c in Clients)
|
foreach (var c in Clients)
|
||||||
|
249
TrueCraft/QueryProtocol.cs
Normal file
249
TrueCraft/QueryProtocol.cs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
|
||||||
|
namespace TrueCraft
|
||||||
|
{
|
||||||
|
public class QueryProtocol
|
||||||
|
{
|
||||||
|
private UdpClient Udp;
|
||||||
|
private int Port;
|
||||||
|
private Timer Timer;
|
||||||
|
private Random Rnd;
|
||||||
|
private IMultiplayerServer Server;
|
||||||
|
private CancellationTokenSource CToken;
|
||||||
|
|
||||||
|
private readonly byte[] ProtocolVersion = new byte[] { 0xFE, 0xFD };
|
||||||
|
private readonly byte Type_Handshake = 0x09;
|
||||||
|
private readonly byte Type_Stat = 0x00;
|
||||||
|
|
||||||
|
private Dictionary<IPEndPoint, QueryUser> UserList;
|
||||||
|
private object UserLock = new object();
|
||||||
|
|
||||||
|
public QueryProtocol(IMultiplayerServer server)
|
||||||
|
{
|
||||||
|
Rnd = new Random();
|
||||||
|
Server = server;
|
||||||
|
}
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
Port = Program.ServerConfiguration.QueryPort;
|
||||||
|
Udp = new UdpClient(Port);
|
||||||
|
Timer = new Timer(ResetUserList, null, 0, 30000);
|
||||||
|
CToken = new CancellationTokenSource();
|
||||||
|
Udp.BeginReceive(HandleReceive, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleReceive(IAsyncResult ar)
|
||||||
|
{
|
||||||
|
if (CToken.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var clientEP = new IPEndPoint(IPAddress.Any, Port);
|
||||||
|
byte[] buffer = Udp.EndReceive(ar, ref clientEP);
|
||||||
|
|
||||||
|
DoReverseEndian(buffer);
|
||||||
|
|
||||||
|
if (CheckVersion(buffer))
|
||||||
|
{
|
||||||
|
if (buffer[2] == Type_Handshake)
|
||||||
|
HandleHandshake(buffer, clientEP);
|
||||||
|
else if (buffer[2] == Type_Stat)
|
||||||
|
{
|
||||||
|
if (buffer.Length == 11)
|
||||||
|
HandleBasicStat(buffer, clientEP);
|
||||||
|
else if (buffer.Length == 15)
|
||||||
|
HandleFullStat(buffer, clientEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
if (CToken.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
Udp.BeginReceive(HandleReceive, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleHandshake(byte[] buffer, IPEndPoint clientEP)
|
||||||
|
{
|
||||||
|
var stream = GetStream(buffer);
|
||||||
|
int sessionId = GetSessionId(stream);
|
||||||
|
|
||||||
|
var user = new QueryUser { SessionId = sessionId, ChallengeToken = Rnd.Next() };
|
||||||
|
lock (UserLock)
|
||||||
|
{
|
||||||
|
if (UserList.ContainsKey(clientEP))
|
||||||
|
UserList.Remove(clientEP);
|
||||||
|
UserList.Add(clientEP, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = GetStream();
|
||||||
|
WriteHead(Type_Handshake, user, response);
|
||||||
|
WriteStringToStream(user.ChallengeToken.ToString(), response.BaseStream);
|
||||||
|
|
||||||
|
SendResponse(response, clientEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleBasicStat(byte[] buffer, IPEndPoint clientEP)
|
||||||
|
{
|
||||||
|
var stream = GetStream(buffer);
|
||||||
|
int sessionId = GetSessionId(stream);
|
||||||
|
int token = GetToken(stream);
|
||||||
|
|
||||||
|
var user = GetUser(clientEP);
|
||||||
|
if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials");
|
||||||
|
|
||||||
|
var stats = GetStats();
|
||||||
|
var response = GetStream();
|
||||||
|
WriteHead(Type_Stat, user, response);
|
||||||
|
WriteStringToStream(stats["hostname"], response.BaseStream);
|
||||||
|
WriteStringToStream(stats["gametype"], response.BaseStream);
|
||||||
|
WriteStringToStream(stats["numplayers"], response.BaseStream);
|
||||||
|
WriteStringToStream(stats["maxplayers"], response.BaseStream);
|
||||||
|
byte[] hostport = BitConverter.GetBytes(UInt16.Parse(stats["hostport"]));
|
||||||
|
Array.Reverse(hostport);//The specification needs little endian short
|
||||||
|
response.Write(hostport);
|
||||||
|
WriteStringToStream(stats["hostip"], response.BaseStream);
|
||||||
|
|
||||||
|
SendResponse(response, clientEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleFullStat(byte[] buffer, IPEndPoint clientEP)
|
||||||
|
{
|
||||||
|
var stream = GetStream(buffer);
|
||||||
|
int sessionId = GetSessionId(stream);
|
||||||
|
int token = GetToken(stream);
|
||||||
|
|
||||||
|
var user = GetUser(clientEP);
|
||||||
|
if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials");
|
||||||
|
|
||||||
|
var stats = GetStats();
|
||||||
|
var response = GetStream();
|
||||||
|
WriteHead(Type_Stat, user, response);
|
||||||
|
WriteStringToStream("SPLITNUM\0\0", response.BaseStream);
|
||||||
|
foreach (var pair in stats)
|
||||||
|
{
|
||||||
|
WriteStringToStream(pair.Key, response.BaseStream);
|
||||||
|
WriteStringToStream(pair.Value, response.BaseStream);
|
||||||
|
}
|
||||||
|
response.Write((byte)0x00);
|
||||||
|
response.Write((byte)0x01);
|
||||||
|
WriteStringToStream("player_\0", response.BaseStream);
|
||||||
|
var players = GetPlayers();
|
||||||
|
foreach (string player in players)
|
||||||
|
WriteStringToStream(player, response.BaseStream);
|
||||||
|
response.Write((byte)0x00);
|
||||||
|
|
||||||
|
SendResponse(response, clientEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckVersion(byte[] ver)
|
||||||
|
{
|
||||||
|
return ver[0] == ProtocolVersion[0] && ver[1] == ProtocolVersion[1];
|
||||||
|
}
|
||||||
|
private int GetSessionId(BinaryReader stream)
|
||||||
|
{
|
||||||
|
stream.BaseStream.Position = 3;
|
||||||
|
return stream.ReadInt32();
|
||||||
|
}
|
||||||
|
private int GetToken(BinaryReader stream)
|
||||||
|
{
|
||||||
|
stream.BaseStream.Position = 7;
|
||||||
|
return stream.ReadInt32();
|
||||||
|
}
|
||||||
|
private BinaryReader GetStream(byte[] buffer)
|
||||||
|
{ return new BinaryReader(new MemoryStream(buffer)); }
|
||||||
|
private BinaryWriter GetStream()
|
||||||
|
{ return new BinaryWriter(new MemoryStream()); }
|
||||||
|
private void WriteHead(byte type, QueryUser user, BinaryWriter stream)
|
||||||
|
{
|
||||||
|
stream.Write(type);
|
||||||
|
stream.Write(user.SessionId);
|
||||||
|
}
|
||||||
|
private void SendResponse(BinaryWriter res, IPEndPoint destination)
|
||||||
|
{
|
||||||
|
byte[] data = ((MemoryStream)res.BaseStream).ToArray();
|
||||||
|
Udp.Send(data, data.Length, destination);
|
||||||
|
}
|
||||||
|
private QueryUser GetUser(IPEndPoint ep)
|
||||||
|
{
|
||||||
|
QueryUser user;
|
||||||
|
lock (UserLock)
|
||||||
|
if (!UserList.TryGetValue(ep, out user)) throw new Exception("Undefined user");
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
private Dictionary<string, string> GetStats()
|
||||||
|
{
|
||||||
|
var stats = new Dictionary<string, string>();
|
||||||
|
stats.Add("hostname", Program.ServerConfiguration.MOTD);
|
||||||
|
stats.Add("gametype", "SMP");
|
||||||
|
stats.Add("game_id", "TRUECRAFT");
|
||||||
|
stats.Add("version", "1.0");
|
||||||
|
stats.Add("plugins", "TrueCraft");
|
||||||
|
stats.Add("map", Server.Worlds.First().Name);
|
||||||
|
stats.Add("numplayers", Server.Clients.Count.ToString());
|
||||||
|
stats.Add("maxplayers", "64");
|
||||||
|
stats.Add("hostport", Program.ServerConfiguration.ServerPort.ToString());
|
||||||
|
stats.Add("hostip", Program.ServerConfiguration.ServerAddress);
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
private List<string> GetPlayers()
|
||||||
|
{
|
||||||
|
var names = new List<string>();
|
||||||
|
lock (Program.Server.ClientLock)
|
||||||
|
foreach (var client in Server.Clients)
|
||||||
|
names.Add(client.Username);
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
private void DoReverseEndian(byte[] buffer)
|
||||||
|
{
|
||||||
|
if (buffer.Length >= 7)
|
||||||
|
{
|
||||||
|
Swap(ref buffer[3], ref buffer[6]);
|
||||||
|
Swap(ref buffer[4], ref buffer[5]);
|
||||||
|
}
|
||||||
|
if (buffer.Length >= 11)
|
||||||
|
{
|
||||||
|
Swap(ref buffer[7], ref buffer[10]);
|
||||||
|
Swap(ref buffer[8], ref buffer[9]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void Swap(ref byte a, ref byte b)
|
||||||
|
{
|
||||||
|
byte c = a;
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
CToken.Cancel();
|
||||||
|
Udp.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetUserList(object state)
|
||||||
|
{
|
||||||
|
lock (UserLock)
|
||||||
|
UserList = new Dictionary<IPEndPoint, QueryUser>();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct QueryUser
|
||||||
|
{
|
||||||
|
public int SessionId;
|
||||||
|
public int ChallengeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] String0ToBytes(string s)
|
||||||
|
{ return Encoding.UTF8.GetBytes(s + "\0"); }
|
||||||
|
private void WriteToStream(byte[] bytes, Stream stream)
|
||||||
|
{ stream.Write(bytes, 0, bytes.Length); }
|
||||||
|
private void WriteStringToStream(string s, Stream stream)
|
||||||
|
{ WriteToStream(String0ToBytes(s), stream); }
|
||||||
|
}
|
||||||
|
}
|
@ -22,12 +22,14 @@ namespace TrueCraft
|
|||||||
|
|
||||||
public ServerConfiguration()
|
public ServerConfiguration()
|
||||||
{
|
{
|
||||||
MOTD = ChatColor.Red + "Welcome to TrueCraft!";
|
MOTD = "Welcome to TrueCraft!";
|
||||||
Debug = new DebugConfiguration();
|
Debug = new DebugConfiguration();
|
||||||
ServerPort = 25565;
|
ServerPort = 25565;
|
||||||
ServerAddress = "0.0.0.0";
|
ServerAddress = "0.0.0.0";
|
||||||
WorldSaveInterval = 30;
|
WorldSaveInterval = 30;
|
||||||
Singleplayer = false;
|
Singleplayer = false;
|
||||||
|
Query = true;
|
||||||
|
QueryPort = 25566;
|
||||||
}
|
}
|
||||||
|
|
||||||
[YamlMember(Alias = "motd")]
|
[YamlMember(Alias = "motd")]
|
||||||
@ -47,5 +49,11 @@ namespace TrueCraft
|
|||||||
|
|
||||||
[YamlIgnore]
|
[YamlIgnore]
|
||||||
public bool Singleplayer { get; set; }
|
public bool Singleplayer { get; set; }
|
||||||
|
|
||||||
|
[YamlMember(Alias = "query")]
|
||||||
|
public bool Query { get; set; }
|
||||||
|
|
||||||
|
[YamlMember(Alias = "queryPort")]
|
||||||
|
public int QueryPort { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,6 +42,7 @@
|
|||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="MultiplayerServer.cs" />
|
<Compile Include="MultiplayerServer.cs" />
|
||||||
|
<Compile Include="QueryProtocol.cs" />
|
||||||
<Compile Include="RemoteClient.cs" />
|
<Compile Include="RemoteClient.cs" />
|
||||||
<Compile Include="Handlers\PacketHandlers.cs" />
|
<Compile Include="Handlers\PacketHandlers.cs" />
|
||||||
<Compile Include="Handlers\LoginHandlers.cs" />
|
<Compile Include="Handlers\LoginHandlers.cs" />
|
||||||
|
Reference in New Issue
Block a user