Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor server events #360

Merged
merged 2 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Obsidian/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ public async Task StartConnectionAsync()
case ClientState.Play:
Debug.Assert(Player is not null);
var packetReceivedEventArgs = new PacketReceivedEventArgs(Player, id, data);
await Server.Events.InvokePacketReceivedAsync(packetReceivedEventArgs);
await Server.Events.PacketReceived.InvokeAsync(packetReceivedEventArgs);

if (!packetReceivedEventArgs.IsCancelled)
{
Expand All @@ -320,7 +320,7 @@ public async Task StartConnectionAsync()
if (State == ClientState.Play)
{
Debug.Assert(Player is not null);
await Server.Events.InvokePlayerLeaveAsync(new PlayerLeaveEventArgs(Player, DateTimeOffset.Now));
await Server.Events.PlayerLeave.InvokeAsync(new PlayerLeaveEventArgs(Player, DateTimeOffset.Now));
}

Disconnected?.Invoke(this);
Expand All @@ -331,7 +331,7 @@ private async Task HandleServerStatusRequestAsync()
{
var status = new ServerStatus(Server);

_ = await Server.Events.InvokeServerStatusRequest(new ServerStatusRequestEventArgs(Server, status));
_ = await Server.Events.ServerStatusRequest.InvokeAsync(new ServerStatusRequestEventArgs(Server, status));

SendPacket(new RequestResponse(status));
}
Expand Down Expand Up @@ -532,7 +532,7 @@ await QueuePacketAsync(new UpdateRecipeBookPacket
await SendPlayerInfoAsync();
await Player.UpdateChunksAsync(distance: 7);
await SendInfoAsync();
await Server.Events.InvokePlayerJoinAsync(new PlayerJoinEventArgs(Player, DateTimeOffset.Now));
await Server.Events.PlayerJoin.InvokeAsync(new PlayerJoinEventArgs(Player, DateTimeOffset.Now));
}

#region Packet sending
Expand Down Expand Up @@ -725,7 +725,7 @@ internal void SendPacket(IClientboundPacket packet)

internal async Task QueuePacketAsync(IClientboundPacket packet)
{
var args = await Server.Events.InvokeQueuePacketAsync(new QueuePacketEventArgs(this, packet));
var args = await Server.Events.QueuePacket.InvokeAsync(new QueuePacketEventArgs(this, packet));
if (args.IsCancelled)
{
Logger.LogDebug("Packet {PacketId} was sent to the queue, however an event handler registered in {Name} has cancelled it.", args.Packet.Id, nameof(Server.Events));
Expand Down
6 changes: 3 additions & 3 deletions Obsidian/Entities/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public async override Task TeleportAsync(VectorF pos)

var tid = Globals.Random.Next(0, 999);

await client.Server.Events.InvokePlayerTeleportedAsync(
await client.Server.Events.PlayerTeleported.InvokeAsync(
new PlayerTeleportEventArgs
(
this,
Expand Down Expand Up @@ -779,7 +779,7 @@ public async Task<bool> GrantPermissionAsync(string permissionNode)
await this.SavePermsAsync();

if (result)
await this.client.Server.Events.InvokePermissionGrantedAsync(new PermissionGrantedEventArgs(this, permissionNode));
await this.client.Server.Events.PermissionGranted.InvokeAsync(new PermissionGrantedEventArgs(this, permissionNode));

return result;
}
Expand All @@ -801,7 +801,7 @@ public async Task<bool> RevokePermissionAsync(string permissionNode)
parent.Children.Remove(childToRemove);

await this.SavePermsAsync();
await this.client.Server.Events.InvokePermissionRevokedAsync(new PermissionRevokedEventArgs(this, permissionNode));
await this.client.Server.Events.PermissionRevoked.InvokeAsync(new PermissionRevokedEventArgs(this, permissionNode));

return true;
}
Expand Down
6 changes: 3 additions & 3 deletions Obsidian/Events/AsyncEvent.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
using System.Runtime.CompilerServices;
using System.Threading;

#nullable enable

namespace Obsidian.Events;

public sealed class AsyncEvent<T> : IEventRegistry
Expand Down Expand Up @@ -68,7 +66,7 @@ public async Task UnregisterAsync(Hook<T> handler)
semaphore.Release();
}

public async ValueTask InvokeAsync(T args)
public async ValueTask<T> InvokeAsync(T args)
{
// This might block hook registration, but that is not expected to happen so often,
// unlike invoking events. That's why it's better to just lock the collection instead
Expand All @@ -89,6 +87,8 @@ public async ValueTask InvokeAsync(T args)
}
}
semaphore.Release();

return args;
}

public bool TryRegisterEvent(MethodInfo method, object? instance, out Delegate? @delegate)
Expand Down
2 changes: 0 additions & 2 deletions Obsidian/Events/AsyncEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using System.Runtime.InteropServices;
using System.Threading;

#nullable enable

namespace Obsidian.Events;

public sealed class AsyncEvent : IEventRegistry
Expand Down
4 changes: 2 additions & 2 deletions Obsidian/Events/EventArgs/BasePacketEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class BasePacketEventArgs : AsyncEventArgs

internal BasePacketEventArgs(Client client, IPacket packet)
{
this.Client = client;
this.Packet = packet;
Client = client;
Packet = packet;
}
}
4 changes: 3 additions & 1 deletion Obsidian/Events/EventArgs/QueuePacketEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public class QueuePacketEventArgs : BasePacketEventArgs, ICancellable
/// <inheritdoc />
public bool IsCancelled { get; private set; }

internal QueuePacketEventArgs(Client client, IPacket packet) : base(client, packet) { }
internal QueuePacketEventArgs(Client client, IPacket packet) : base(client, packet)
{
}

/// <inheritdoc />
public void Cancel()
Expand Down
3 changes: 0 additions & 3 deletions Obsidian/Events/IEventRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System.Reflection;

#nullable enable

namespace Obsidian.Events;

public interface IEventRegistry
{
public string? Name { get; }

public bool TryRegisterEvent(MethodInfo method, object? instance, out Delegate? @delegate);

public bool UnregisterEvent(Delegate @delegate);
}
142 changes: 18 additions & 124 deletions Obsidian/Events/MinecraftEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,134 +5,28 @@ namespace Obsidian.Events;

public class MinecraftEventHandler
{
public AsyncEvent<PacketReceivedEventArgs> PacketReceived;
public AsyncEvent<QueuePacketEventArgs> QueuePacket;
public AsyncEvent<PlayerJoinEventArgs> PlayerJoin;
public AsyncEvent<PlayerLeaveEventArgs> PlayerLeave;
public AsyncEvent<PlayerTeleportEventArgs> PlayerTeleported;
public AsyncEvent<PermissionGrantedEventArgs> PermissionGranted;
public AsyncEvent<PermissionRevokedEventArgs> PermissionRevoked;
public AsyncEvent<ContainerClickEventArgs> ClickEvent;
public AsyncEvent<BlockBreakEventArgs> BlockBreak;
public AsyncEvent<IncomingChatMessageEventArgs> IncomingChatMessage;
public AsyncEvent<ServerStatusRequestEventArgs> ServerStatusRequest;
public AsyncEvent<EntityInteractEventArgs> EntityInteract;
public AsyncEvent<PlayerAttackEntityEventArgs> PlayerAttackEntity;
public AsyncEvent<PlayerInteractEventArgs> PlayerInteract;
public AsyncEvent<ContainerClosedEventArgs> ContainerClosed;
public AsyncEvent ServerTick;
public AsyncEvent<PacketReceivedEventArgs> PacketReceived = new(nameof(PacketReceived), HandleException);
public AsyncEvent<QueuePacketEventArgs> QueuePacket = new(nameof(QueuePacket), HandleException);
public AsyncEvent<PlayerJoinEventArgs> PlayerJoin = new(nameof(PlayerJoin), HandleException);
public AsyncEvent<PlayerLeaveEventArgs> PlayerLeave = new(nameof(PlayerLeave), HandleException);
public AsyncEvent<PlayerTeleportEventArgs> PlayerTeleported = new(nameof(PlayerTeleported), HandleException);
public AsyncEvent<PermissionGrantedEventArgs> PermissionGranted = new(nameof(PermissionGranted), HandleException);
public AsyncEvent<PermissionRevokedEventArgs> PermissionRevoked = new(nameof(PermissionRevoked), HandleException);
public AsyncEvent<ContainerClickEventArgs> ContainerClick = new(nameof(ContainerClick), HandleException);
public AsyncEvent<BlockBreakEventArgs> BlockBreak = new(nameof(BlockBreak), HandleException);
public AsyncEvent<IncomingChatMessageEventArgs> IncomingChatMessage = new(nameof(IncomingChatMessage), HandleException);
public AsyncEvent<ServerStatusRequestEventArgs> ServerStatusRequest = new(nameof(ServerStatusRequest), HandleException);
public AsyncEvent<EntityInteractEventArgs> EntityInteract = new(nameof(EntityInteract), HandleException);
public AsyncEvent<PlayerAttackEntityEventArgs> PlayerAttackEntity = new(nameof(PlayerAttackEntity), HandleException);
public AsyncEvent<PlayerInteractEventArgs> PlayerInteract = new(nameof(PlayerInteract), HandleException);
public AsyncEvent<ContainerClosedEventArgs> ContainerClosed = new(nameof(ContainerClosed), HandleException);
public AsyncEvent ServerTick = new(nameof(ServerTick), HandleException);

public MinecraftEventHandler()
private static void HandleException(AsyncEvent e, Exception exception)
{
// Events that don't need additional arguments
PacketReceived = new("PacketReceived", HandleException);
QueuePacket = new("QueuePacket", HandleException);

PlayerJoin = new("PlayerJoin", HandleException);
PlayerLeave = new("PlayerLeave", HandleException);
ServerTick = new("ServerTick", HandleException);
PermissionGranted = new("PermissionGranted", HandleException);
PermissionRevoked = new("PermissionRevoked", HandleException);
ClickEvent = new("ContainerClick", HandleException);
BlockBreak = new("BlockBreak", HandleException);
IncomingChatMessage = new("IncomingChatMessage", HandleException);
PlayerTeleported = new("PlayerTeleported", HandleException);
ServerStatusRequest = new("ServerStatusRequest", HandleException);
EntityInteract = new("EntityInteract", HandleException);
PlayerAttackEntity = new("PlayerAttackEntity", HandleException);
PlayerInteract = new("PlayerInteract", HandleException);
ContainerClosed = new("ContainerClosed", HandleException);
}

private void HandleException(AsyncEvent e, Exception exception)
{
}

private void HandleException<T>(AsyncEvent<T> e, Exception exception)
{
}

internal async ValueTask<ContainerClosedEventArgs> InvokeContainerClosedAsync(ContainerClosedEventArgs eventArgs)
{
await ContainerClosed.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<QueuePacketEventArgs> InvokeQueuePacketAsync(QueuePacketEventArgs eventArgs)
{
await QueuePacket.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<ContainerClickEventArgs> InvokeContainerClickAsync(ContainerClickEventArgs eventArgs)
{
await ClickEvent.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<BlockBreakEventArgs> InvokeBlockBreakAsync(BlockBreakEventArgs eventArgs)
{
await BlockBreak.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<PlayerInteractEventArgs> InvokePlayerInteractAsync(PlayerInteractEventArgs eventArgs)
{
await PlayerInteract.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<IncomingChatMessageEventArgs> InvokeIncomingChatMessageAsync(IncomingChatMessageEventArgs eventArgs)
{
await IncomingChatMessage.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<PlayerTeleportEventArgs> InvokePlayerTeleportedAsync(PlayerTeleportEventArgs eventArgs)
{
await PlayerTeleported.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<PermissionGrantedEventArgs> InvokePermissionGrantedAsync(PermissionGrantedEventArgs eventArgs)
{
await PermissionGranted.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<PermissionRevokedEventArgs> InvokePermissionRevokedAsync(PermissionRevokedEventArgs eventArgs)
{
await PermissionRevoked.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<EntityInteractEventArgs> InvokeEntityInteractAsync(EntityInteractEventArgs eventArgs)
{
await EntityInteract.InvokeAsync(eventArgs);
return eventArgs;
}

internal async ValueTask<PlayerAttackEntityEventArgs> InvokePlayerAttackEntityAsync(PlayerAttackEntityEventArgs eventArgs)
{
await PlayerAttackEntity.InvokeAsync(eventArgs);
return eventArgs;
}

internal ValueTask InvokePacketReceivedAsync(PacketReceivedEventArgs eventArgs) =>
PacketReceived.InvokeAsync(eventArgs);

internal ValueTask InvokePlayerJoinAsync(PlayerJoinEventArgs eventArgs) =>
PlayerJoin.InvokeAsync(eventArgs);

internal ValueTask InvokePlayerLeaveAsync(PlayerLeaveEventArgs eventArgs) =>
PlayerLeave.InvokeAsync(eventArgs);

internal ValueTask InvokeServerTickAsync() =>
ServerTick.InvokeAsync();

internal async ValueTask<ServerStatusRequestEventArgs> InvokeServerStatusRequest(ServerStatusRequestEventArgs eventArgs)
private static void HandleException<T>(AsyncEvent<T> e, Exception exception)
{
await ServerStatusRequest.InvokeAsync(eventArgs);
return eventArgs;
}
}
2 changes: 1 addition & 1 deletion Obsidian/Net/Packets/Play/CloseContainerPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public async ValueTask HandleAsync(Server server, Player player)
if (WindowId == 0)
return;

await server.Events.InvokeContainerClosedAsync(new ContainerClosedEventArgs(player) { Container = player.OpenedContainer! });
await server.Events.ContainerClosed.InvokeAsync(new ContainerClosedEventArgs(player) { Container = player.OpenedContainer! });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private async Task HandleMouseClick(BaseContainer container, Server server, Play
{
if (!CarriedItem.IsAir)
{
var @event = await server.Events.InvokeContainerClickAsync(new ContainerClickEventArgs(player, container, CarriedItem)
var @event = await server.Events.ContainerClick.InvokeAsync(new ContainerClickEventArgs(player, container, CarriedItem)
{
Slot = slot
});
Expand Down
6 changes: 3 additions & 3 deletions Obsidian/Net/Packets/Play/Serverbound/InteractPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ public async ValueTask HandleAsync(Server server, Player player)
switch (Type)
{
case InteractionType.Interact:
await server.Events.InvokeEntityInteractAsync(new EntityInteractEventArgs(player, entity, server, Sneaking));
await server.Events.EntityInteract.InvokeAsync(new EntityInteractEventArgs(player, entity, server, Sneaking));
break;

case InteractionType.Attack:
await server.Events.InvokePlayerAttackEntityAsync(new PlayerAttackEntityEventArgs(player, entity, server, Sneaking));
await server.Events.PlayerAttackEntity.InvokeAsync(new PlayerAttackEntityEventArgs(player, entity, server, Sneaking));
break;

case InteractionType.InteractAt:
await server.Events.InvokeEntityInteractAsync(new EntityInteractEventArgs(player, entity, server, Hand, Target, Sneaking));
await server.Events.EntityInteract.InvokeAsync(new EntityInteractEventArgs(player, entity, server, Hand, Target, Sneaking));
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public async ValueTask HandleAsync(Server server, Player player)
SequenceID = Sequence
});

var blockBreakEvent = await server.Events.InvokeBlockBreakAsync(new BlockBreakEventArgs(server, player, block, Position));
var blockBreakEvent = await server.Events.BlockBreak.InvokeAsync(new BlockBreakEventArgs(server, player, block, Position));
if (blockBreakEvent.Handled)
return;
}
Expand Down
2 changes: 1 addition & 1 deletion Obsidian/Net/Packets/Play/Serverbound/UseItemOnPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async ValueTask HandleAsync(Server server, Player player)

if (TagsRegistry.Blocks.PlayersCanInteract.Entries.Contains(interactedBlock.RegistryId) && !player.Sneaking)
{
await server.Events.InvokePlayerInteractAsync(new PlayerInteractEventArgs(player)
await server.Events.PlayerInteract.InvokeAsync(new PlayerInteractEventArgs(player)
{
Item = currentItem,
Block = interactedBlock,
Expand Down
2 changes: 1 addition & 1 deletion Obsidian/Net/Packets/Play/Serverbound/UseItemPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public partial class UseItemPacket : IServerboundPacket

public async ValueTask HandleAsync(Server server, Player player)
{
await server.Events.InvokePlayerInteractAsync(new PlayerInteractEventArgs(player)
await server.Events.PlayerInteract.InvokeAsync(new PlayerInteractEventArgs(player)
{
Item = this.Hand == Hand.MainHand ? player.GetHeldItem() : player.GetOffHandItem(),
Hand = this.Hand,
Expand Down
4 changes: 2 additions & 2 deletions Obsidian/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ internal async Task HandleIncomingMessageAsync(ChatMessagePacket packet, Client
var format = "<{0}> {1}";
var message = packet.Message;

var chat = await Events.InvokeIncomingChatMessageAsync(new IncomingChatMessageEventArgs(source.Player, message, format));
var chat = await Events.IncomingChatMessage.InvokeAsync(new IncomingChatMessageEventArgs(source.Player, message, format));
if (chat.IsCancelled)
return;

Expand Down Expand Up @@ -658,7 +658,7 @@ private async Task LoopAsync()
{
while (await timer.WaitForNextTickAsync())
{
await Events.InvokeServerTickAsync();
await Events.ServerTick.InvokeAsync();

keepAliveTicks++;
if (keepAliveTicks > (Config.KeepAliveInterval / 50)) // to clarify: one tick is 50 milliseconds. 50 * 200 = 10000 millis means 10 seconds
Expand Down