Skip to content

Commit

Permalink
Next (+1 squashed commits)
Browse files Browse the repository at this point in the history
Squashed commits:

[ec3080ad7] # This is a combination of 2 commits.

Add parallel starting

Revert port
  • Loading branch information
CrosRoad95 committed Nov 13, 2024
1 parent 5fe7b3d commit 5b9f49d
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 15 deletions.
2 changes: 2 additions & 0 deletions SlipeServer.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using System.Threading;
using SlipeServer.Example;
using SlipeServer.Scripting.Luau;
using SlipeServer.Server.Resources;

namespace SlipeServer.Console;

Expand Down Expand Up @@ -104,6 +105,7 @@ public Program(string[] args)
services.AddScoped<TestService>();
services.AddSingleton<PacketReplayerService>();
services.AddScoped<SampleScopedService>();
services.AddSingleton<ResourceService>();
services.AddHttpClient();
Expand Down
3 changes: 3 additions & 0 deletions SlipeServer.Example/Resources/ResourceA/client.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
addCommandHandler("sampltest", function()
outputChatBox("ResourceA is running!")
end)
3 changes: 3 additions & 0 deletions SlipeServer.Example/Resources/ResourceB/client.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
addCommandHandler("sampltest", function()
outputChatBox("ResourceB is running!")
end)
44 changes: 44 additions & 0 deletions SlipeServer.Example/ResourcesLogic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.Extensions.Logging;
using SlipeServer.Server;
using SlipeServer.Server.Elements;
using SlipeServer.Server.Resources;
using SlipeServer.Server.Resources.Providers;
using SlipeServer.Server.Services;

namespace SlipeServer.Example;

public class ResourcesLogic
{
private readonly ChatBox chatBox;
private readonly ResourceService resourceService;
private readonly ILogger logger;

public ResourcesLogic(MtaServer mtaServer, ChatBox chatBox, IResourceProvider resourceProvider, ResourceService resourceService, ILogger logger)
{
this.chatBox = chatBox;
this.resourceService = resourceService;
this.logger = logger;
this.resourceService.StartResource("ResourceA");
this.resourceService.StartResource("ResourceB");
this.resourceService.AllStarted += HandleAllStarted;
mtaServer.PlayerJoined += HandlePlayerJoin;
}

private async void HandlePlayerJoin(Player player)
{
try
{
await this.resourceService.StartResourcesForPlayer(player);
}
catch (Exception ex)
{
this.logger.LogError(ex, "Failed to start resources for {playerName}", player.Name);
}
}

private void HandleAllStarted(Player player)
{
Console.WriteLine("All resources started for: {0}", player.Name);
this.chatBox.Output($"All resources started for: {player.Name}");
}
}
1 change: 1 addition & 0 deletions SlipeServer.Example/ServerBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public static class ServerBuilderExtensions
public static ServerBuilder AddExampleLogic(this ServerBuilder builder)
{
builder.AddLogic<ServerExampleLogic>();
builder.AddLogic<ResourcesLogic>();

return builder;
}
Expand Down
14 changes: 14 additions & 0 deletions SlipeServer.Example/SlipeServer.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,18 @@
<ProjectReference Include="..\SlipeServer.Server\SlipeServer.Server.csproj" />
<ProjectReference Include="..\SlipeServer.SourceGenerators\SlipeServer.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<Folder Include="Resources\ResourceB\" />
<Folder Include="Resources\ResourceA\" />
</ItemGroup>

<ItemGroup>
<None Update="Resources\ResourceA\client.lua">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\ResourceB\client.lua">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions SlipeServer.HostBuilderExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using SlipeServer.Server.Resources.Serving;
using SlipeServer.Server.ServerBuilders;
using SlipeServer.Example;
using SlipeServer.Server.Resources;


Configuration? configuration = null;
Expand All @@ -25,6 +26,7 @@
services.AddHttpClient();
services.AddSingleton<IResourceServer, BasicHttpServer>();
services.AddSingleton<ResourceService>();
services.AddHostedService<SampleHostedService>(); // Use instead of logics
services.TryAddSingleton<ILogger>(x => x.GetRequiredService<ILogger<MtaServer>>());
Expand Down
13 changes: 12 additions & 1 deletion SlipeServer.Packets/Definitions/Resources/ResourceStartPacket.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using SlipeServer.Packets.Builder;
using SlipeServer.Packets.Enums;
using SlipeServer.Packets.Reader;
using SlipeServer.Packets.Structs;
using System.Collections.Generic;
using System.Text;

namespace SlipeServer.Packets.Definitions.Resources;

Expand All @@ -13,7 +15,7 @@ public class ResourceStartPacket : Packet
public override PacketPriority Priority => PacketPriority.High;

public string Name { get; set; }
public ushort NetId { get; }
public ushort NetId { get; set; }
public ElementId ResourceDynamicElementId { get; set; }
public ushort UncachedScriptCount { get; }
public string MinServerVersion { get; }
Expand All @@ -24,6 +26,11 @@ public class ResourceStartPacket : Packet
public IEnumerable<string> ExportedFunctions { get; }
public ElementId ResourceElementId { get; }

public ResourceStartPacket()
{

}

public ResourceStartPacket(
string name,
ushort netId,
Expand Down Expand Up @@ -53,6 +60,10 @@ IEnumerable<string> exportedFunctions

public override void Read(byte[] bytes)
{
var reader = new PacketReader(bytes);
var len = reader.GetByte();
this.Name = Encoding.UTF8.GetString(reader.GetBytes(len));
this.NetId = reader.GetUInt16();
}

public override byte[] Write()
Expand Down
1 change: 1 addition & 0 deletions SlipeServer.Packets/Reader/PacketReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public bool[] GetBits(int count)
public uint GetUint32() => BitConverter.ToUInt32(GetBytes(4), 0);
public ulong GetUint64() => BitConverter.ToUInt64(GetBytes(8), 0);
public short GetInt16() => BitConverter.ToInt16(GetBytes(2), 0);
public ushort GetUInt16() => BitConverter.ToUInt16(GetBytes(2), 0);
public int GetInt32() => BitConverter.ToInt32(GetBytes(4), 0);
public long GetInt64() => BitConverter.ToInt64(GetBytes(8), 0);
public float GetFloat() => BitConverter.ToSingle(GetBytes(4), 0);
Expand Down
44 changes: 44 additions & 0 deletions SlipeServer.Server.TestTools/TestResourceProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using SlipeServer.Server.Resources.Interpreters;
using SlipeServer.Server.Resources.Providers;
using SlipeServer.Server.Resources;
using System.Collections.Generic;

namespace SlipeServer.Server.TestTools;

public class TestResourceProvider : IResourceProvider
{
private readonly Dictionary<string, Resource> resources = [];
private readonly object netIdLock = new();
private ushort netId = 0;

public void AddResource(Resource resource)
{
this.resources[resource.Name] = resource;
}

public Resource GetResource(string name)
{
return this.resources[name];
}

public IEnumerable<Resource> GetResources()
{
return this.resources.Values;
}

public void Refresh() { }

private IEnumerable<Resource> IndexResourceDirectory(string directory) => [];

public IEnumerable<string> GetFilesForResource(string name) => [];

public byte[] GetFileContent(string resource, string file) => [];

public ushort ReserveNetId()
{
lock (this.netIdLock)
return this.netId++;
}

public void AddResourceInterpreter(IResourceInterpreter resourceInterpreter) { }
}
34 changes: 33 additions & 1 deletion SlipeServer.Server.TestTools/TestingServer.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
using Castle.Core.Logging;
using FluentAssertions;
using FluentAssertions.Common;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
using SlipeServer.Net.Wrappers;
using SlipeServer.Packets;
using SlipeServer.Packets.Definitions.Lua;
using SlipeServer.Packets.Definitions.Lua.ElementRpc;
using SlipeServer.Packets.Definitions.Resources;
using SlipeServer.Packets.Enums;
using SlipeServer.Packets.Lua.Event;
using SlipeServer.Server.Clients;
using SlipeServer.Server.Elements;
using SlipeServer.Server.Resources;
using SlipeServer.Server.Resources.Providers;
using SlipeServer.Server.Resources.Serving;
using SlipeServer.Server.ServerBuilders;
using System;
using System.Collections.Generic;
using System.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;
using ILogger = Microsoft.Extensions.Logging.ILogger;

namespace SlipeServer.Server.TestTools;
Expand Down Expand Up @@ -76,12 +81,14 @@ private void SetupSendPacketMocks()
this.NetWrapperMock.Setup(x => x.SendPacket(It.IsAny<ulong>(), It.IsAny<ushort>(), It.IsAny<Packet>()))
.Callback((ulong address, ushort version, Packet packet) =>
{
var data = packet.Write();
this.packetReducer.EnqueuePacket(this.clients[this.NetWrapperMock.Object][address], packet.PacketId, data);
this.sendPacketCalls.Add(new SendPacketCall()
{
Address = address,
Version = version,
PacketId = packet.PacketId,
Data = packet.Write(),
Data = data,
Priority = packet.Priority,
Reliability = packet.Reliability
});
Expand Down Expand Up @@ -153,6 +160,26 @@ public void VerifyPacketSent(PacketId packetId, TPlayer to, byte[] data = null,
).Should().Be(count);
}

public void VerifyResourceStartedPacketSent(TPlayer player, Resource resource, int count = 1)
{
var sendPacketCalls = this.sendPacketCalls
.Where(x => x.PacketId == PacketId.PACKET_ID_RESOURCE_START && x.Address == player.GetAddress());

int startedCount = 0;

var packet = new ResourceStartPacket();
foreach (var sendPacketCall in sendPacketCalls)
{
packet.Read(sendPacketCall.Data);
if(packet.NetId == resource.NetId)
{
startedCount++;
}
}

startedCount.Should().Be(count);
}

public void VerifyLuaElementRpcPacketSent(ElementRpcFunction packetId, TPlayer to, byte[] data = null, int count = 1)
{
this.sendPacketCalls.Count(x =>
Expand Down Expand Up @@ -192,6 +219,11 @@ public void VerifyLuaEventTriggered(string eventName, TPlayer to, Element source
count.Should().Be(expectedCount);
}

public T CreateInstance<T>(params object[] parameters)
{
return ActivatorUtilities.CreateInstance<T>(this.serviceProvider, parameters);
}

public void ResetPacketCountVerification() => this.sendPacketCalls.Clear();

public uint GenerateBinaryAddress() => ++this.binaryAddressCounter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SlipeServer.Packets.Definitions.Resources;
using SlipeServer.Packets.Enums;
using SlipeServer.Server.Clients;
using SlipeServer.Server.PacketHandling.Handlers;
using SlipeServer.Server.Resources;
using SlipeServer.Server.Resources.Providers;
using SlipeServer.Server.TestTools;
using System.Linq;
using System.Threading.Tasks;
using Xunit;

namespace SlipeServer.Server.Tests.Integration.Services;

public class ClientPlayerResourceStartedPacketHandler : IPacketHandler<ResourceStartPacket>
{
public PacketId PacketId => PacketId.PACKET_ID_RESOURCE_START;

public ClientPlayerResourceStartedPacketHandler()
{
}

public void HandlePacket(IClient client, ResourceStartPacket packet)
{
client.Player.TriggerResourceStarted(packet.NetId);
}
}

public class ResourceServiceTests
{
class ResourceA : Resource
{
public ResourceA(MtaServer server) : base(server, server.RootElement, "ResourceA") { }
}

class ResourceB : Resource
{
public ResourceB(MtaServer server) : base(server, server.RootElement, "ResourceB") { }
}

[InlineData(true)]
[InlineData(false)]
[Theory]
public async Task ResourceServiceShouldWork(bool parallel)
{
var server = new TestingServer((Configuration?)null, builder =>
{
builder.ConfigureServices(services =>
{
services.RemoveAll<IResourceProvider>();
services.AddSingleton<TestResourceProvider>();
services.AddSingleton<IResourceProvider>(x => x.GetRequiredService<TestResourceProvider>());
});
});

server.RegisterPacketHandler<ClientPlayerResourceStartedPacketHandler, ResourceStartPacket>();

var resourceProvider = server.GetRequiredService<TestResourceProvider>();
var resourceA = new ResourceA(server);
server.AddAdditionalResource(resourceA, []);
resourceProvider.AddResource(resourceA);
var resourceB = new ResourceB(server);
server.AddAdditionalResource(resourceB, []);
resourceProvider.AddResource(resourceB);

var resourceService = server.CreateInstance<ResourceService>();
using var monitor = resourceService.Monitor();

resourceService.StartResource("ResourceA");
resourceService.StartResource("ResourceB");

var player = server.AddFakePlayer();
await resourceService.StartResourcesForPlayer(player, parallel);

using var _ = new AssertionScope();
monitor.OccurredEvents.Select(x => x.EventName).Should().BeEquivalentTo(["Started", "Started", "AllStarted"]);
server.VerifyResourceStartedPacketSent(player, resourceA);
server.VerifyResourceStartedPacketSent(player, resourceB);
}
}
Loading

0 comments on commit 5b9f49d

Please sign in to comment.