Make event handler async, while preserving the order of incoming events.
This commit is contained in:
parent
90d5c2a16c
commit
1acd32b986
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PkmnLibSharp.Battling.ChoiceTurn;
|
||||
using PkmnLibSharp.Battling.Events;
|
||||
|
@ -173,8 +174,10 @@ namespace PkmnLibSharp.Battling
|
|||
return Creaturelib.Generated.Battle.HasVolatileScript(Ptr, key.ToPtr()) == 1;
|
||||
}
|
||||
|
||||
private List<BattleEventListener> _listeners = new List<BattleEventListener>();
|
||||
public void RegisterEventListener(BattleEventListener listener)
|
||||
{
|
||||
_listeners.Add(listener);
|
||||
Creaturelib.Generated.Battle.RegisterEventListener(Ptr, listener.FunctionPtr).Assert();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,42 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PkmnLibSharp.Battling.Events
|
||||
{
|
||||
public class BattleEventListener
|
||||
{
|
||||
public delegate void BattleEventDelegate(EventData evt);
|
||||
public delegate Task BattleEventDelegate(EventData evt);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void BattleEventPtrDelegate(IntPtr ptr);
|
||||
|
||||
private readonly BattleEventDelegate _del;
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
private readonly BattleEventPtrDelegate _innerDel;
|
||||
internal readonly IntPtr FunctionPtr;
|
||||
private Task _currentTask;
|
||||
|
||||
public BattleEventListener(BattleEventDelegate del)
|
||||
{
|
||||
_del = del;
|
||||
_innerDel = OnEventPtr;
|
||||
FunctionPtr = Marshal.GetFunctionPointerForDelegate(_innerDel);
|
||||
FunctionPtr = Marshal.GetFunctionPointerForDelegate<BattleEventPtrDelegate>(_innerDel);
|
||||
}
|
||||
|
||||
private void OnEventPtr(IntPtr ptr)
|
||||
{
|
||||
// If we're still registering another event, wait until that's done. This ensures events always arrive in
|
||||
// the correct order.
|
||||
_currentTask?.Wait();
|
||||
// We do however want to run the event handler async, so that the battle code can keep running up till its
|
||||
// next event.
|
||||
_currentTask = Task.Run(() => InternalRunner(ptr));
|
||||
}
|
||||
|
||||
private async Task InternalRunner(IntPtr ptr)
|
||||
{
|
||||
var wrapped = WrapEventPtr(ptr);
|
||||
_del.Invoke(wrapped);
|
||||
await _del.Invoke(wrapped);
|
||||
}
|
||||
|
||||
private static EventData WrapEventPtr(IntPtr ptr)
|
||||
|
|
BIN
PkmnLibSharp/Native/libCreatureLib.so (Stored with Git LFS)
BIN
PkmnLibSharp/Native/libCreatureLib.so (Stored with Git LFS)
Binary file not shown.
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using PkmnLibSharp.Battling;
|
||||
using PkmnLibSharp.Battling.ChoiceTurn;
|
||||
|
@ -94,6 +95,7 @@ namespace PkmnLibSharpTests.Battling.BattleTests
|
|||
battle.RegisterEventListener(new BattleEventListener(evt =>
|
||||
{
|
||||
evts.Add(evt);
|
||||
return Task.CompletedTask;
|
||||
}));
|
||||
|
||||
battle.SwitchPokemon(0, 0, p1.GetAtIndex(0));
|
||||
|
|
Loading…
Reference in New Issue