diff --git a/TrueCraft.API/Server/ChatMessageEventArgs.cs b/TrueCraft.API/Server/ChatMessageEventArgs.cs new file mode 100644 index 0000000..a9d5418 --- /dev/null +++ b/TrueCraft.API/Server/ChatMessageEventArgs.cs @@ -0,0 +1,22 @@ +using System; +using TrueCraft.API.Networking; + +namespace TrueCraft.API.Server +{ + public class ChatMessageEventArgs : EventArgs + { + public ChatMessageEventArgs(IRemoteClient client, string message) + { + Client = client; + Message = message; + PreventDefault = false; + } + + public IRemoteClient Client { get; set; } + public string Message { get; set; } + /// + /// If set to true, the server won't send the default message back to the client. + /// + public bool PreventDefault { get; set; } + } +} \ No newline at end of file diff --git a/TrueCraft.API/Server/IMultiplayerServer.cs b/TrueCraft.API/Server/IMultiplayerServer.cs index 4edd038..65af6f3 100644 --- a/TrueCraft.API/Server/IMultiplayerServer.cs +++ b/TrueCraft.API/Server/IMultiplayerServer.cs @@ -15,6 +15,8 @@ namespace TrueCraft.API.Server public interface IMultiplayerServer { + event EventHandler ChatMessageReceived; + IPacketReader PacketReader { get; } IList Clients { get; } IList Worlds { get; } @@ -26,5 +28,6 @@ namespace TrueCraft.API.Server void AddLogProvider(ILogProvider provider); void Log(LogCategory category, string text, params object[] parameters); IEntityManager GetEntityManagerForWorld(IWorld world); + void SendMessage(string message, params object[] parameters); } } \ No newline at end of file diff --git a/TrueCraft.API/TrueCraft.API.csproj b/TrueCraft.API/TrueCraft.API.csproj index 94f0f35..ac3a34f 100644 --- a/TrueCraft.API/TrueCraft.API.csproj +++ b/TrueCraft.API/TrueCraft.API.csproj @@ -72,6 +72,7 @@ + diff --git a/TrueCraft/Handlers/LoginHandlers.cs b/TrueCraft/Handlers/LoginHandlers.cs index e663e19..096ffee 100644 --- a/TrueCraft/Handlers/LoginHandlers.cs +++ b/TrueCraft/Handlers/LoginHandlers.cs @@ -30,19 +30,19 @@ namespace TrueCraft.Handlers client.QueuePacket(new DisconnectPacket("Server has no worlds configured.")); else { - server.Log(LogCategory.Notice, "{0} joined the server.", client.Username); // TODO: Mention the same thing in chat client.LoggedIn = true; client.Entity = new PlayerEntity(client.Username); client.World = server.Worlds[0]; server.GetEntityManagerForWorld(client.World).SpawnEntity(client.Entity); client.QueuePacket(new LoginResponsePacket(0, 0, Dimension.Overworld)); - client.ChunkRadius = 2; + client.ChunkRadius = 3; client.UpdateChunks(); client.QueuePacket(new WindowItemsPacket(0, client.Inventory.GetSlots())); client.QueuePacket(new SpawnPositionPacket(0, 16, 0)); client.QueuePacket(new SetPlayerPositionPacket(0, 16, 17, 0, 0, 0, true)); server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(10), client.SendKeepAlive); server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(1), client.ExpandChunkRadius); + server.SendMessage(ChatColor.Yellow + "{0} joined the server.", client.Username); } } } diff --git a/TrueCraft/Handlers/PacketHandlers.cs b/TrueCraft/Handlers/PacketHandlers.cs index 497ed7e..b608104 100644 --- a/TrueCraft/Handlers/PacketHandlers.cs +++ b/TrueCraft/Handlers/PacketHandlers.cs @@ -3,6 +3,7 @@ using TrueCraft.API; using TrueCraft.API.Server; using TrueCraft.Core.Networking.Packets; using TrueCraft.API.Networking; +using TrueCraft.API.Logging; namespace TrueCraft.Handlers { @@ -27,15 +28,16 @@ namespace TrueCraft.Handlers // TODO } - internal static void HandleChatMessage(IPacket _packet, IRemoteClient _client, IMultiplayerServer server) + internal static void HandleChatMessage(IPacket _packet, IRemoteClient _client, IMultiplayerServer _server) { // TODO: Abstract this to support things like commands // TODO: Sanitize messages var packet = (ChatMessagePacket)_packet; - foreach (var client in server.Clients) - { - client.SendMessage(ChatColor.Yellow + string.Format("<{0}> {1}", _client.Username, packet.Message)); - } + var server = (MultiplayerServer)_server; + var args = new ChatMessageEventArgs(_client, packet.Message); + server.OnChatMessageReceived(args); + if (!args.PreventDefault) + server.SendMessage("<{0}> {1}", _client.Username, packet.Message); } } } \ No newline at end of file diff --git a/TrueCraft/MultiplayerServer.cs b/TrueCraft/MultiplayerServer.cs index 7b399c0..b16bbee 100644 --- a/TrueCraft/MultiplayerServer.cs +++ b/TrueCraft/MultiplayerServer.cs @@ -9,11 +9,14 @@ using System.Collections.Generic; using TrueCraft.API.World; using TrueCraft.API.Logging; using TrueCraft.Core.Networking.Packets; +using TrueCraft.API; namespace TrueCraft { public class MultiplayerServer : IMultiplayerServer { + public event EventHandler ChatMessageReceived; + public IPacketReader PacketReader { get; private set; } public IList Clients { get; private set; } public IList Worlds { get; private set; } @@ -104,6 +107,22 @@ namespace TrueCraft return null; } + public void SendMessage(string message, params object[] parameters) + { + var compiled = string.Format(message, parameters); + foreach (var client in Clients) + { + client.SendMessage(compiled); + Log(LogCategory.Notice, compiled); + } + } + + protected internal void OnChatMessageReceived(ChatMessageEventArgs e) + { + if (ChatMessageReceived != null) + ChatMessageReceived(this, e); + } + private void DisconnectClient(IRemoteClient _client) { var client = (RemoteClient)_client; @@ -130,7 +149,7 @@ namespace TrueCraft for (int i = 0; i < Clients.Count; i++) { var client = Clients[i] as RemoteClient; - if (client.PacketQueue.Count != 0) + while (client.PacketQueue.Count != 0) { IPacket packet; while (!client.PacketQueue.TryDequeue(out packet)) { } @@ -139,6 +158,7 @@ namespace TrueCraft { DisconnectClient(client); i--; + break; } } if (client.DataAvailable)