Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ade957f62 | ||
|
|
c06c84ca9c | ||
|
|
c9ae5e3bd2 |
9 changed files with 174 additions and 38 deletions
|
|
@ -41,4 +41,7 @@ public static partial class EventSink
|
|||
|
||||
public static event Action ServerStarted;
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
20
Projects/Server/Events/MessageBus.cs
Normal file
20
Projects/Server/Events/MessageBus.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using NATS.Client.Core;
|
||||
using NATS.Client.JetStream;
|
||||
using NATS.Net;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public static class MessageBus
|
||||
{
|
||||
private static NatsClient natsClient;
|
||||
public static NatsClient Client => natsClient;
|
||||
|
||||
private static INatsJSContext jetstreamContext;
|
||||
public static INatsJSContext Context => jetstreamContext;
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
natsClient = new NatsClient();
|
||||
jetstreamContext = natsClient.CreateJetStreamContext();
|
||||
}
|
||||
}
|
||||
|
|
@ -233,6 +233,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
SetLastMoved();
|
||||
|
||||
World.AddEntity(this);
|
||||
|
||||
MessageBus.Publish("items.created", $"{Serial}:{itemID}");
|
||||
}
|
||||
|
||||
public Item(Serial serial) => Serial = serial;
|
||||
|
|
@ -1072,6 +1074,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
{
|
||||
writer.WriteEncodedInt(info.m_SavedFlags);
|
||||
}
|
||||
|
||||
MessageBus.Publish("items.serialize", $"{Serial}:{ItemID}");
|
||||
}
|
||||
|
||||
public void MoveToWorld(WorldLocation worldLocation)
|
||||
|
|
@ -3036,6 +3040,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
|
||||
// if (version < 9)
|
||||
VerifyCompactInfo();
|
||||
|
||||
MessageBus.Publish("items.deserialize", $"{Serial}:{ItemID}");
|
||||
}
|
||||
|
||||
private void FixHolding_Sandbox()
|
||||
|
|
|
|||
|
|
@ -192,7 +192,9 @@ public static class Core
|
|||
fullPath = fi.Directory.EnumerateFiles(
|
||||
fi.Name,
|
||||
new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
|
||||
).FirstOrDefault()?.FullName;
|
||||
)
|
||||
.FirstOrDefault()
|
||||
?.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +320,7 @@ public static class Core
|
|||
|
||||
process.Start();
|
||||
}
|
||||
|
||||
logger.Information("Restart done");
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -383,13 +386,15 @@ public static class Core
|
|||
Utility.PopColor();
|
||||
|
||||
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 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
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
".TrimMultiline());
|
||||
".TrimMultiline()
|
||||
);
|
||||
Utility.PopColor();
|
||||
|
||||
Console.CancelKeyPress += Console_CancelKeyPressed;
|
||||
|
|
@ -429,6 +434,8 @@ public static class Core
|
|||
|
||||
TileMatrixLoader.LoadTileMatrix();
|
||||
|
||||
MessageBus.Start();
|
||||
|
||||
RegionJsonSerializer.LoadRegions();
|
||||
World.Load();
|
||||
|
||||
|
|
@ -436,6 +443,7 @@ public static class Core
|
|||
|
||||
TcpServer.Start();
|
||||
PingServer.Start();
|
||||
|
||||
EventSink.InvokeServerStarted();
|
||||
RunEventLoop();
|
||||
}
|
||||
|
|
@ -564,7 +572,8 @@ public static class Core
|
|||
if (World.DirtyTrackingEnabled)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.3.2" />
|
||||
<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="System.IO.Hashing" Version="8.0.0" />
|
||||
|
||||
|
|
|
|||
119
Projects/UOContent/Commands/Broadcast.cs
Normal file
119
Projects/UOContent/Commands/Broadcast.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using Server.Network;
|
||||
using NATS.Client;
|
||||
using NATS.Client.Core;
|
||||
using NATS.Client.JetStream;
|
||||
using NATS.Client.JetStream.Models;
|
||||
using NATS.Net;
|
||||
|
||||
namespace Server.Commands;
|
||||
|
||||
[JsonSerializable(typeof(BroadcastPayload))]
|
||||
internal partial class BroadcastJsonContext : JsonSerializerContext;
|
||||
|
||||
public record BroadcastPayload
|
||||
{
|
||||
[JsonPropertyName("hue")]
|
||||
public int Hue { get; set; } = 0x482;
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public static class Broadcast
|
||||
{
|
||||
private static INatsJSConsumer incomingBroadcastsConsumer;
|
||||
|
||||
private static readonly NatsJsonContextSerializer<BroadcastPayload> broadcastSerializer =
|
||||
new(BroadcastJsonContext.Default);
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
CommandSystem.Register("BCast", AccessLevel.GameMaster, BroadcastMessage_OnCommand);
|
||||
CommandSystem.Register("SMsg", AccessLevel.Counselor, StaffMessage_OnCommand);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
StartBroadcasts();
|
||||
}
|
||||
|
||||
[Usage("BCast <text>")]
|
||||
[Aliases("B", "BC")]
|
||||
[Description("Broadcasts a message to everyone online.")]
|
||||
public static void BroadcastMessage_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
EmitBroadcast($"Staff message from {e.Mobile.Name}:", 0x482);
|
||||
EmitBroadcast($"{e.ArgString}", 0x21);
|
||||
// BroadcastMessage(AccessLevel.Player, 0x482, $"Staff message from {e.Mobile.Name}:");
|
||||
// BroadcastMessage(AccessLevel.Player, 0x482, e.ArgString);
|
||||
}
|
||||
|
||||
[Usage("SMsg <text>")]
|
||||
[Aliases("S", "SM")]
|
||||
[Description("Broadcasts a message to all online staff.")]
|
||||
public static void StaffMessage_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
BroadcastMessage(AccessLevel.Counselor, e.Mobile.SpeechHue, $"[{e.Mobile.Name}] {e.ArgString}");
|
||||
}
|
||||
|
||||
public static async void EmitBroadcast(string message, int hue)
|
||||
{
|
||||
await MessageBus.Client.PublishAsync(
|
||||
subject: "broadcast.all",
|
||||
data: new BroadcastPayload()
|
||||
{
|
||||
Message = message,
|
||||
Hue = hue,
|
||||
},
|
||||
serializer: broadcastSerializer
|
||||
);
|
||||
}
|
||||
|
||||
public static void BroadcastMessage(AccessLevel ac, int hue, string message)
|
||||
{
|
||||
foreach (var state in NetState.Instances)
|
||||
{
|
||||
var m = state.Mobile;
|
||||
|
||||
if (m?.AccessLevel >= ac)
|
||||
{
|
||||
m.SendMessage(hue, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async void StartBroadcasts()
|
||||
{
|
||||
await MessageBus.Context.CreateStreamAsync(
|
||||
new StreamConfig(name: "BROADCASTS", subjects: ["broadcast.>"])
|
||||
);
|
||||
|
||||
incomingBroadcastsConsumer = await MessageBus.Context.CreateOrUpdateConsumerAsync(
|
||||
"BROADCASTS",
|
||||
new ConsumerConfig("broadcast_incoming_consumer")
|
||||
);
|
||||
|
||||
CancellationTokenSource cancellationTokenSource = new();
|
||||
|
||||
await foreach (var msg in incomingBroadcastsConsumer.ConsumeAsync(
|
||||
serializer: broadcastSerializer,
|
||||
cancellationToken: cancellationTokenSource.Token
|
||||
))
|
||||
{
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,8 +33,6 @@ namespace Server.Commands
|
|||
Register("Help", AccessLevel.Player, Help_OnCommand);
|
||||
Register("Move", AccessLevel.GameMaster, Move_OnCommand);
|
||||
Register("Client", AccessLevel.Counselor, Client_OnCommand);
|
||||
Register("SMsg", AccessLevel.Counselor, StaffMessage_OnCommand);
|
||||
Register("BCast", AccessLevel.GameMaster, BroadcastMessage_OnCommand);
|
||||
Register("Bank", AccessLevel.GameMaster, Bank_OnCommand);
|
||||
Register("Echo", AccessLevel.Counselor, Echo_OnCommand);
|
||||
Register("Sound", AccessLevel.GameMaster, Sound_OnCommand);
|
||||
|
|
@ -625,36 +623,6 @@ namespace Server.Commands
|
|||
}
|
||||
}
|
||||
|
||||
[Usage("SMsg <text>")]
|
||||
[Aliases("S", "SM")]
|
||||
[Description("Broadcasts a message to all online staff.")]
|
||||
public static void StaffMessage_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
BroadcastMessage(AccessLevel.Counselor, e.Mobile.SpeechHue, $"[{e.Mobile.Name}] {e.ArgString}");
|
||||
}
|
||||
|
||||
[Usage("BCast <text>")]
|
||||
[Aliases("B", "BC")]
|
||||
[Description("Broadcasts a message to everyone online.")]
|
||||
public static void BroadcastMessage_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var state in NetState.Instances)
|
||||
{
|
||||
var m = state.Mobile;
|
||||
|
||||
if (m?.AccessLevel >= ac)
|
||||
{
|
||||
m.SendMessage(hue, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("AutoPageNotify")]
|
||||
[Aliases("APN")]
|
||||
[Description("Toggles your auto-page-notify status.")]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public static class Broadcasts
|
||||
|
|
@ -6,6 +8,13 @@ namespace Server.Misc
|
|||
{
|
||||
EventSink.ServerCrashed += EventSink_Crashed;
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
<Delete Files="..\..\Distribution\Assemblies\ModernUO.Serialization.Annotations.dll" ContinueOnError="true" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NATS.Net" Version="2.5.1" />
|
||||
<ProjectReference Include="..\Server\Server.csproj" Private="false" PrivateAssets="All" IncludeAssets="None">
|
||||
<IncludeInPackage>false</IncludeInPackage>
|
||||
</ProjectReference>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue