NATS
This commit is contained in:
parent
3fc55e4db3
commit
c9ae5e3bd2
7 changed files with 135 additions and 8 deletions
|
|
@ -41,4 +41,7 @@ public static partial class EventSink
|
||||||
|
|
||||||
public static event Action ServerStarted;
|
public static event Action ServerStarted;
|
||||||
public static void InvokeServerStarted() => ServerStarted?.Invoke();
|
public static void InvokeServerStarted() => ServerStarted?.Invoke();
|
||||||
|
|
||||||
|
public static event Action<string, int> IncomingMessage;
|
||||||
|
public static void InvokeIncomingMessage(string message, int hue) => IncomingMessage?.Invoke(message, hue);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
97
Projects/Server/Events/MessageBus.cs
Normal file
97
Projects/Server/Events/MessageBus.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using NATS.Client;
|
||||||
|
using NATS.Client.Core;
|
||||||
|
using NATS.Client.JetStream;
|
||||||
|
using NATS.Client.JetStream.Models;
|
||||||
|
using NATS.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(BroadcastMessage))]
|
||||||
|
internal partial class BroadcastJsonContext : JsonSerializerContext;
|
||||||
|
|
||||||
|
public record BroadcastMessage
|
||||||
|
{
|
||||||
|
[JsonPropertyName("hue")]
|
||||||
|
public int Hue { get; set; } = 0x482;
|
||||||
|
|
||||||
|
[JsonPropertyName("message")]
|
||||||
|
public string? Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MessageBus
|
||||||
|
{
|
||||||
|
private static NatsClient natsClient;
|
||||||
|
private static INatsJSContext jetstreamContext;
|
||||||
|
private static INatsJSConsumer incomingBroadcastsConsumer;
|
||||||
|
private static CancellationTokenSource cancellationTokenSource;
|
||||||
|
|
||||||
|
private static NatsJsonContextSerializer<BroadcastMessage> broadcastSerializer =
|
||||||
|
new (BroadcastJsonContext.Default);
|
||||||
|
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
natsClient = new NatsClient();
|
||||||
|
jetstreamContext = natsClient.CreateJetStreamContext();
|
||||||
|
|
||||||
|
StartBroadcasts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async void StartBroadcasts()
|
||||||
|
{
|
||||||
|
await jetstreamContext.CreateStreamAsync(
|
||||||
|
new StreamConfig(name: "INCOMING_NOTIFICATIONS", subjects: ["incoming.notifications.>"])
|
||||||
|
);
|
||||||
|
|
||||||
|
incomingBroadcastsConsumer = await jetstreamContext.CreateOrUpdateConsumerAsync(
|
||||||
|
"INCOMING_NOTIFICATIONS",
|
||||||
|
new ConsumerConfig("incoming_broadcasts_consumer")
|
||||||
|
{
|
||||||
|
FilterSubject = "incoming.notifications.broadcast"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
await foreach (var msg in incomingBroadcastsConsumer.ConsumeAsync(
|
||||||
|
cancellationToken: cancellationTokenSource.Token,
|
||||||
|
serializer: broadcastSerializer
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if (msg.Data == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Message Received w/ null Data");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Message Received {msg.Data}");
|
||||||
|
EventSink.InvokeIncomingMessage(msg.Data.Message, msg.Data.Hue);
|
||||||
|
await msg.AckAsync(cancellationToken: cancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void SendBroadcast(string message, int hue)
|
||||||
|
{
|
||||||
|
await natsClient.PublishAsync(
|
||||||
|
subject: "incoming.notifications.broadcast",
|
||||||
|
data: new BroadcastMessage()
|
||||||
|
{
|
||||||
|
Message = message,
|
||||||
|
Hue = hue,
|
||||||
|
},
|
||||||
|
serializer: broadcastSerializer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async void Publish<T>(string subject, T data, INatsSerializer<T> serializer = null)
|
||||||
|
{
|
||||||
|
await natsClient.PublishAsync<T>(subject, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Kill()
|
||||||
|
{
|
||||||
|
cancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -233,6 +233,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
||||||
SetLastMoved();
|
SetLastMoved();
|
||||||
|
|
||||||
World.AddEntity(this);
|
World.AddEntity(this);
|
||||||
|
|
||||||
|
MessageBus.Publish("items.created", $"{Serial}:{itemID}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item(Serial serial) => Serial = serial;
|
public Item(Serial serial) => Serial = serial;
|
||||||
|
|
@ -1072,6 +1074,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
||||||
{
|
{
|
||||||
writer.WriteEncodedInt(info.m_SavedFlags);
|
writer.WriteEncodedInt(info.m_SavedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageBus.Publish("items.serialize", $"{Serial}:{ItemID}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveToWorld(WorldLocation worldLocation)
|
public void MoveToWorld(WorldLocation worldLocation)
|
||||||
|
|
@ -3036,6 +3040,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
||||||
|
|
||||||
// if (version < 9)
|
// if (version < 9)
|
||||||
VerifyCompactInfo();
|
VerifyCompactInfo();
|
||||||
|
|
||||||
|
MessageBus.Publish("items.deserialize", $"{Serial}:{ItemID}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FixHolding_Sandbox()
|
private void FixHolding_Sandbox()
|
||||||
|
|
|
||||||
|
|
@ -189,9 +189,11 @@ public static class Core
|
||||||
if (fi.Directory != null && Directory.Exists(fi.Directory.FullName))
|
if (fi.Directory != null && Directory.Exists(fi.Directory.FullName))
|
||||||
{
|
{
|
||||||
fullPath = fi.Directory.EnumerateFiles(
|
fullPath = fi.Directory.EnumerateFiles(
|
||||||
fi.Name,
|
fi.Name,
|
||||||
new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
|
new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
|
||||||
).FirstOrDefault()?.FullName;
|
)
|
||||||
|
.FirstOrDefault()
|
||||||
|
?.FullName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,6 +319,7 @@ public static class Core
|
||||||
|
|
||||||
process.Start();
|
process.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Information("Restart done");
|
logger.Information("Restart done");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
@ -380,13 +383,15 @@ public static class Core
|
||||||
Utility.PopColor();
|
Utility.PopColor();
|
||||||
|
|
||||||
Utility.PushColor(ConsoleColor.DarkGray);
|
Utility.PushColor(ConsoleColor.DarkGray);
|
||||||
Console.WriteLine(@"Copyright 2019-2023 ModernUO Development Team
|
Console.WriteLine(
|
||||||
|
@"Copyright 2019-2023 ModernUO Development Team
|
||||||
This program comes with ABSOLUTELY NO WARRANTY;
|
This program comes with ABSOLUTELY NO WARRANTY;
|
||||||
This is free software, and you are welcome to redistribute it under certain conditions.
|
This is free software, and you are welcome to redistribute it under certain conditions.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
".TrimMultiline());
|
".TrimMultiline()
|
||||||
|
);
|
||||||
Utility.PopColor();
|
Utility.PopColor();
|
||||||
|
|
||||||
Console.CancelKeyPress += Console_CancelKeyPressed;
|
Console.CancelKeyPress += Console_CancelKeyPressed;
|
||||||
|
|
@ -426,6 +431,8 @@ public static class Core
|
||||||
|
|
||||||
TileMatrixLoader.LoadTileMatrix();
|
TileMatrixLoader.LoadTileMatrix();
|
||||||
|
|
||||||
|
MessageBus.Start();
|
||||||
|
|
||||||
RegionJsonSerializer.LoadRegions();
|
RegionJsonSerializer.LoadRegions();
|
||||||
World.Load();
|
World.Load();
|
||||||
|
|
||||||
|
|
@ -433,6 +440,7 @@ public static class Core
|
||||||
|
|
||||||
TcpServer.Start();
|
TcpServer.Start();
|
||||||
PingServer.Start();
|
PingServer.Start();
|
||||||
|
|
||||||
EventSink.InvokeServerStarted();
|
EventSink.InvokeServerStarted();
|
||||||
RunEventLoop();
|
RunEventLoop();
|
||||||
}
|
}
|
||||||
|
|
@ -561,7 +569,8 @@ public static class Core
|
||||||
if (World.DirtyTrackingEnabled)
|
if (World.DirtyTrackingEnabled)
|
||||||
{
|
{
|
||||||
var manualDirtyCheckingAttribute = type.GetCustomAttribute<ManualDirtyCheckingAttribute>(false);
|
var manualDirtyCheckingAttribute = type.GetCustomAttribute<ManualDirtyCheckingAttribute>(false);
|
||||||
var codeGennedAttribute = type.GetCustomAttribute<ModernUO.Serialization.SerializationGeneratorAttribute>(false);
|
var codeGennedAttribute =
|
||||||
|
type.GetCustomAttribute<ModernUO.Serialization.SerializationGeneratorAttribute>(false);
|
||||||
|
|
||||||
if (manualDirtyCheckingAttribute == null && codeGennedAttribute == null)
|
if (manualDirtyCheckingAttribute == null && codeGennedAttribute == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.3.2" />
|
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.3.2" />
|
||||||
<PackageReference Include="LibDeflate.Bindings" Version="1.0.2.120" />
|
<PackageReference Include="LibDeflate.Bindings" Version="1.0.2.120" />
|
||||||
|
<PackageReference Include="NATS.Net" Version="2.5.1" />
|
||||||
<PackageReference Include="PollGroup" Version="1.5.1" />
|
<PackageReference Include="PollGroup" Version="1.5.1" />
|
||||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -638,8 +638,10 @@ namespace Server.Commands
|
||||||
[Description("Broadcasts a message to everyone online.")]
|
[Description("Broadcasts a message to everyone online.")]
|
||||||
public static void BroadcastMessage_OnCommand(CommandEventArgs e)
|
public static void BroadcastMessage_OnCommand(CommandEventArgs e)
|
||||||
{
|
{
|
||||||
BroadcastMessage(AccessLevel.Player, 0x482, $"Staff message from {e.Mobile.Name}:");
|
MessageBus.SendBroadcast($"Staff message from {e.Mobile.Name}:", 0x482);
|
||||||
BroadcastMessage(AccessLevel.Player, 0x482, e.ArgString);
|
MessageBus.SendBroadcast($"{e.ArgString}", 0x21);
|
||||||
|
// BroadcastMessage(AccessLevel.Player, 0x482, $"Staff message from {e.Mobile.Name}:");
|
||||||
|
// BroadcastMessage(AccessLevel.Player, 0x482, e.ArgString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BroadcastMessage(AccessLevel ac, int hue, string message)
|
public static void BroadcastMessage(AccessLevel ac, int hue, string message)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Server.Misc
|
namespace Server.Misc
|
||||||
{
|
{
|
||||||
public static class Broadcasts
|
public static class Broadcasts
|
||||||
|
|
@ -6,6 +8,13 @@ namespace Server.Misc
|
||||||
{
|
{
|
||||||
EventSink.ServerCrashed += EventSink_Crashed;
|
EventSink.ServerCrashed += EventSink_Crashed;
|
||||||
EventSink.Shutdown += EventSink_Shutdown;
|
EventSink.Shutdown += EventSink_Shutdown;
|
||||||
|
EventSink.IncomingMessage += EventSink_IncomingMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EventSink_IncomingMessage(string message, int hue)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Incoming Message");
|
||||||
|
World.Broadcast(hue, true, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EventSink_Crashed(ServerCrashedEventArgs e)
|
public static void EventSink_Crashed(ServerCrashedEventArgs e)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue