diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events.meta b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events.meta
new file mode 100644
index 000000000..ed6f3c3db
--- /dev/null
+++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f9fd123f0bc24231b09e4b95a69c07a9
+timeCreated: 1727174219
\ No newline at end of file
diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs
new file mode 100644
index 000000000..6023af9a7
--- /dev/null
+++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs
@@ -0,0 +1,35 @@
+using ChainSafe.Gaming.RPC.Events;
+using ChainSafe.Gaming.Web3.Build;
+
+namespace ChainSafe.Gaming.EVM.Events
+{
+ public static class EventExtensionsUnity
+ {
+ ///
+ /// Enable EVM Event Manager for the Web3 client.
+ ///
+ /// The Web3 services collection.
+ /// (Optional) Event Poller configuration. This will only be used for the WebGL platform.
+ ///
+ ///
+ /// For all the platforms that support multithreading the WebSocket strategy will be used.
+ /// In WebGL this will bind the Polling strategy which will fetch data periodically.
+ ///
+ public static IWeb3ServiceCollection UseEvents(this IWeb3ServiceCollection services, PollingEventManagerConfig eventPollerConfig = null)
+ {
+#if !UNITY_WEBGL
+ services.UseEventsWithWebSocket();
+#else
+ if (eventPollerConfig == null)
+ {
+ services.UseEventsWithPolling();
+ }
+ else
+ {
+ services.UseEventsWithPolling(eventPollerConfig);
+ }
+#endif
+ return services;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs.meta b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs.meta
new file mode 100644
index 000000000..edf0a4756
--- /dev/null
+++ b/Packages/io.chainsafe.web3-unity/Runtime/Scripts/EVM/Events/EventExtensionsUnity.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 45634a8f8b564bdba2d7040fa7116ae0
+timeCreated: 1727174273
\ No newline at end of file
diff --git a/src/ChainSafe.Gaming.Mud/MudExtensions.cs b/src/ChainSafe.Gaming.Mud/MudExtensions.cs
index 50f707421..5d0a38f73 100644
--- a/src/ChainSafe.Gaming.Mud/MudExtensions.cs
+++ b/src/ChainSafe.Gaming.Mud/MudExtensions.cs
@@ -57,11 +57,6 @@ public static IWeb3ServiceCollection UseMud(this IWeb3ServiceCollection services
// Storage strategies
services.AddTransient(); // todo implement OffchainIndexerMudStorage, then register it in the next line
- if (!services.IsBound())
- {
- services.UseEvents();
- }
-
if (!services.IsBound())
{
services.UseNethereumAdapters();
diff --git a/src/ChainSafe.Gaming.Mud/MudFacade.cs b/src/ChainSafe.Gaming.Mud/MudFacade.cs
index dc4503e0d..a7b793bc1 100644
--- a/src/ChainSafe.Gaming.Mud/MudFacade.cs
+++ b/src/ChainSafe.Gaming.Mud/MudFacade.cs
@@ -28,7 +28,7 @@ public Task BuildWorld(IMudWorldConfig worldConfig)
{
var stopwatch = Stopwatch.StartNew();
var world = worldFactory.Build(worldConfig);
- logWriter.Log($"Loaded world {worldConfig.ContractAddress} in {stopwatch.Elapsed}");
+ logWriter.Log($"Loaded MUD world {worldConfig.ContractAddress} in {stopwatch.Elapsed}");
return world;
}
}
diff --git a/src/ChainSafe.Gaming.Mud/Storages/InMemory/InMemoryMudStorage.cs b/src/ChainSafe.Gaming.Mud/Storages/InMemory/InMemoryMudStorage.cs
index 476de062c..6fe3705d4 100644
--- a/src/ChainSafe.Gaming.Mud/Storages/InMemory/InMemoryMudStorage.cs
+++ b/src/ChainSafe.Gaming.Mud/Storages/InMemory/InMemoryMudStorage.cs
@@ -5,6 +5,7 @@
using System.Threading.Tasks;
using ChainSafe.Gaming.Mud.Tables;
using ChainSafe.Gaming.RPC.Events;
+using ChainSafe.Gaming.Web3;
using ChainSafe.Gaming.Web3.Core.Nethereum;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Mud;
@@ -18,25 +19,34 @@ namespace ChainSafe.Gaming.Mud.Storages.InMemory
public class InMemoryMudStorage : IMudStorage
{
private readonly INethereumWeb3Adapter nWeb3;
- private readonly EventManager eventManager;
+ private readonly IEventManager eventManager;
private readonly SemaphoreSlim storeUpdateSemaphore = new(1);
private IInMemoryMudStorageConfig config;
private InMemoryTableRepository inMemoryRepository;
+ private string worldAddress;
- public InMemoryMudStorage(INethereumWeb3Adapter nWeb3, EventManager eventManager)
+ public InMemoryMudStorage(INethereumWeb3Adapter nWeb3, IEventManager eventManager)
{
this.eventManager = eventManager;
this.nWeb3 = nWeb3;
}
+ public InMemoryMudStorage(INethereumWeb3Adapter nWeb3)
+ {
+ throw new Web3Exception($"{nameof(InMemoryMudStorage)} requires {nameof(IEventManager)} to work. " +
+ $"Please don't forget to register an {nameof(IEventManager)} in order to use " +
+ $"{nameof(InMemoryMudStorage)}.");
+ }
+
public event RecordSetDelegate RecordSet;
public event RecordDeletedDelegate RecordDeleted;
public async Task Initialize(IMudStorageConfig mudStorageConfig, string worldAddress)
{
+ this.worldAddress = worldAddress;
config = (IInMemoryMudStorageConfig)mudStorageConfig;
inMemoryRepository = new InMemoryTableRepository();
var storeLogProcessingService = new StoreEventsLogProcessingService(nWeb3, worldAddress);
@@ -46,18 +56,18 @@ await storeLogProcessingService.ProcessAllStoreChangesAsync(
null,
CancellationToken.None);
- await eventManager.Subscribe(OnStoreSetRecord);
- await eventManager.Subscribe(OnStoreSpliceStaticData);
- await eventManager.Subscribe(OnStoreSpliceDynamicDataEventDTO);
- await eventManager.Subscribe(OnStoreDeleteRecord);
+ await eventManager.Subscribe(OnStoreSetRecord, worldAddress);
+ await eventManager.Subscribe(OnStoreSpliceStaticData, worldAddress);
+ await eventManager.Subscribe(OnStoreSpliceDynamicDataEventDTO, worldAddress);
+ await eventManager.Subscribe(OnStoreDeleteRecord, worldAddress);
}
public async Task Terminate()
{
- await eventManager.Unsubscribe(OnStoreSetRecord);
- await eventManager.Unsubscribe(OnStoreSpliceStaticData);
- await eventManager.Unsubscribe(OnStoreSpliceDynamicDataEventDTO);
- await eventManager.Unsubscribe(OnStoreDeleteRecord);
+ await eventManager.Unsubscribe(OnStoreSetRecord, worldAddress);
+ await eventManager.Unsubscribe(OnStoreSpliceStaticData, worldAddress);
+ await eventManager.Unsubscribe(OnStoreSpliceDynamicDataEventDTO, worldAddress);
+ await eventManager.Unsubscribe(OnStoreDeleteRecord, worldAddress);
}
public async Task