diff --git a/MinecraftDiscordBot/ClientScript.lua b/MinecraftDiscordBot/ClientScript.lua
index fa04108..fe399d5 100644
--- a/MinecraftDiscordBot/ClientScript.lua
+++ b/MinecraftDiscordBot/ClientScript.lua
@@ -188,10 +188,51 @@ local function peripheralAttachEventListener(socket)
end
end
+local function listAsSet(list)
+ local asSet = {}
+ for i,elem in pairs(list) do asSet[elem] = true end
+ return asSet
+end
+
+local function joinSets(a, b)
+ local joined = {}
+ for elem,exists in pairs(a) do if exists then joined[elem] = true end end
+ for elem,exists in pairs(b) do if exists then joined[elem] = true end end
+ return joined
+end
+
+local function playerStatusEventListener(socket)
+ local players = {}
+ while true do
+ local pd = peripheral.find("playerDetector")
+ if not not pd then
+ players = listAsSet(pd.getOnlinePlayers())
+ break
+ end
+ printError("playerDetector not connected!")
+ end
+ while true do
+ local pd = peripheral.find("playerDetector")
+ if not not pd then
+ local newPlayers = listAsSet(pd.getOnlinePlayers())
+ for player,_ in pairs(joinSets(players, newPlayers)) do
+ if players[player] and (not newPlayers[player]) then
+ sendJson(socket, {type = "playerstatus", player = player, status = false})
+ elseif (not players[player]) and newPlayers[player] then
+ sendJson(socket, {type = "playerstatus", player = player, status = true})
+ end
+ end
+ players = newPlayers
+ end
+ sleep(1)
+ end
+end
+
local function eventListeners(socket)
parallel.waitForAny(
termWaiter,
function() chatEventListener(socket) end,
+ function() playerStatusEventListener(socket) end,
function() peripheralDetachEventListener(socket) end,
function() peripheralAttachEventListener(socket) end
)
diff --git a/MinecraftDiscordBot/MinecraftDiscordBot.csproj b/MinecraftDiscordBot/MinecraftDiscordBot.csproj
index 3cf40ea..c025260 100644
--- a/MinecraftDiscordBot/MinecraftDiscordBot.csproj
+++ b/MinecraftDiscordBot/MinecraftDiscordBot.csproj
@@ -6,7 +6,7 @@
enable
enable
Linux
- 1.1.2
+ 1.1.3
Michael Chen
$(Authors)
https://gitlab.com/chenmichael/mcdiscordbot
diff --git a/MinecraftDiscordBot/Models/Message.cs b/MinecraftDiscordBot/Models/Message.cs
index 40bf9d7..064ef2d 100644
--- a/MinecraftDiscordBot/Models/Message.cs
+++ b/MinecraftDiscordBot/Models/Message.cs
@@ -1,6 +1,7 @@
using Discord.WebSocket;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using System.Diagnostics;
namespace MinecraftDiscordBot.Models;
@@ -39,14 +40,17 @@ public abstract class Message {
}
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class CapabilityMessage : Message {
private const string TYPE = "roles";
public override string Type => TYPE;
[JsonProperty("role", Required = Required.Always)]
public string[] Role { get; set; } = default!;
+ public override string ToString() => $"Capabilities: {string.Join(", ", Role)}";
}
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class ReplyMessage : Message {
private const string TYPE = "reply";
public override string Type => TYPE;
@@ -60,19 +64,35 @@ public class ReplyMessage : Message {
public int Total { get; set; } = 1;
[JsonProperty("success", Required = Required.DisallowNull)]
public ResultState State { get; set; } = ResultState.Successful;
+ public override string ToString() => $"Reply [{AnswerId}] {State} ({Chunk}/{Total}) Length {Result.Length}";
}
public abstract class EventMessage : Message { }
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class PeripheralDetachEvent : EventMessage {
private const string TYPE = "peripheral_detach";
public override string Type => TYPE;
[JsonProperty("side", Required = Required.Always)]
public string Side { get; set; } = default!;
+ public override string ToString() => $"Detached '{Side}'!";
}
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
+public class PlayerStatusEvent : EventMessage {
+ private const string TYPE = "playerstatus";
+ public override string Type => TYPE;
+ [JsonProperty("player", Required = Required.Always)]
+ public string Player { get; set; } = default!;
+ [JsonProperty("status", Required = Required.Always)]
+ public bool Online { get; set; }
+ public override string ToString() => $"{Player} is now {(Online ? "on" : "off")}line!";
+}
+
+[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class PeripheralAttachEvent : EventMessage {
private const string TYPE = "peripheral";
public override string Type => TYPE;
@@ -80,6 +100,7 @@ public class PeripheralAttachEvent : EventMessage {
public string Side => Peripheral.Side;
[JsonProperty("peripheral", Required = Required.Always)]
public Peripheral Peripheral { get; set; } = default!;
+ public override string ToString() => $"Attached {Peripheral}!";
}
public class Peripheral {
@@ -89,9 +110,11 @@ public class Peripheral {
public string Type { get; set; } = default!;
[JsonProperty("methods", Required = Required.Always)]
public string[] Methods { get; set; } = default!;
+ public override string ToString() => $"{Type} at '{Side}'";
}
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class ChatEvent : EventMessage {
private const string TYPE = "chat";
public override string Type => TYPE;
@@ -103,9 +126,11 @@ public class ChatEvent : EventMessage {
public string UUID { get; set; } = default!;
[JsonProperty("hidden", Required = Required.Always)]
public bool IsHidden { get; set; }
+ public override string ToString() => $"{(IsHidden ? "HIDDEN: " : string.Empty)}[{Username}] {Message} ({UUID})";
}
[MessageType(TYPE)]
+[DebuggerDisplay($"{{{nameof(ToString)}(),nq}}")]
public class RequestMessage : Message {
private const string TYPE = "request";
public override string Type => TYPE;
@@ -121,4 +146,5 @@ public class RequestMessage : Message {
public string Method { get; set; }
[JsonProperty("params")]
public Dictionary Parameters { get; }
+ public override string ToString() => $"Request [{AnswerId}] {Method}({JsonConvert.SerializeObject(Parameters)})";
}
diff --git a/MinecraftDiscordBot/Program.cs b/MinecraftDiscordBot/Program.cs
index 11930a7..77db653 100644
--- a/MinecraftDiscordBot/Program.cs
+++ b/MinecraftDiscordBot/Program.cs
@@ -60,6 +60,7 @@ public class Program : IDisposable, ICommandHandler, IUserRoleMana
_computer = new(this);
_computer.ChatMessageReceived += MinecraftMessageReceived;
_computer.SocketChanged += ComputerConnectedChanged;
+ _computer.PlayerStatusChanged += PlayerStatusChanged;
_computer.PeripheralAttached += PeripheralAttached;
_computer.PeripheralDetached += PeripheralDetached;
_administrators = config.Administrators.ToHashSet();
@@ -74,6 +75,8 @@ public class Program : IDisposable, ICommandHandler, IUserRoleMana
_whitelistedChannels = config.Channels.ToHashSet();
}
+ private void PlayerStatusChanged(object? sender, PlayerStatusEvent e)
+ => _ = Task.Run(() => Broadcast(i => i.SendMessageAsync($"{e.Player} just {(e.Online ? "joined" : "left")} the server!")));
private void PeripheralAttached(object? sender, PeripheralAttachEvent e) => LogInfo("Computer", $"Peripheral {e.Peripheral.Type} was attached on side {e.Side}.");
private void PeripheralDetached(object? sender, PeripheralDetachEvent e) => LogInfo("Computer", $"Peripheral on side {e.Side} was detached.");
private void ComputerConnectedChanged(object? sender, IWebSocketConnection? e)
diff --git a/MinecraftDiscordBot/Services/RootCommandService.cs b/MinecraftDiscordBot/Services/RootCommandService.cs
index 80e055d..17a52f3 100644
--- a/MinecraftDiscordBot/Services/RootCommandService.cs
+++ b/MinecraftDiscordBot/Services/RootCommandService.cs
@@ -26,6 +26,7 @@ public class RootCommandService : CommandRouter, ITaskWaitSource {
}
public event EventHandler? ChatMessageReceived;
+ public event EventHandler? PlayerStatusChanged;
public event EventHandler? PeripheralAttached;
public event EventHandler? PeripheralDetached;
public event EventHandler? SocketChanged;
@@ -49,6 +50,9 @@ public class RootCommandService : CommandRouter, ITaskWaitSource {
case ChatEvent msg:
ChatMessageReceived?.Invoke(this, msg);
break;
+ case PlayerStatusEvent msg:
+ PlayerStatusChanged?.Invoke(this, msg);
+ break;
case PeripheralAttachEvent msg:
PeripheralAttached?.Invoke(this, msg);
break;