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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using PkmnLibSharp.Battling.ChoiceTurn;
|
using PkmnLibSharp.Battling.ChoiceTurn;
|
||||||
using PkmnLibSharp.Battling.Events;
|
using PkmnLibSharp.Battling.Events;
|
||||||
|
@ -173,8 +174,10 @@ namespace PkmnLibSharp.Battling
|
||||||
return Creaturelib.Generated.Battle.HasVolatileScript(Ptr, key.ToPtr()) == 1;
|
return Creaturelib.Generated.Battle.HasVolatileScript(Ptr, key.ToPtr()) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<BattleEventListener> _listeners = new List<BattleEventListener>();
|
||||||
public void RegisterEventListener(BattleEventListener listener)
|
public void RegisterEventListener(BattleEventListener listener)
|
||||||
{
|
{
|
||||||
|
_listeners.Add(listener);
|
||||||
Creaturelib.Generated.Battle.RegisterEventListener(Ptr, listener.FunctionPtr).Assert();
|
Creaturelib.Generated.Battle.RegisterEventListener(Ptr, listener.FunctionPtr).Assert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,42 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PkmnLibSharp.Battling.Events
|
namespace PkmnLibSharp.Battling.Events
|
||||||
{
|
{
|
||||||
public class BattleEventListener
|
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 delegate void BattleEventPtrDelegate(IntPtr ptr);
|
||||||
|
|
||||||
private readonly BattleEventDelegate _del;
|
private readonly BattleEventDelegate _del;
|
||||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||||
private readonly BattleEventPtrDelegate _innerDel;
|
private readonly BattleEventPtrDelegate _innerDel;
|
||||||
internal readonly IntPtr FunctionPtr;
|
internal readonly IntPtr FunctionPtr;
|
||||||
|
private Task _currentTask;
|
||||||
|
|
||||||
public BattleEventListener(BattleEventDelegate del)
|
public BattleEventListener(BattleEventDelegate del)
|
||||||
{
|
{
|
||||||
_del = del;
|
_del = del;
|
||||||
_innerDel = OnEventPtr;
|
_innerDel = OnEventPtr;
|
||||||
FunctionPtr = Marshal.GetFunctionPointerForDelegate(_innerDel);
|
FunctionPtr = Marshal.GetFunctionPointerForDelegate<BattleEventPtrDelegate>(_innerDel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEventPtr(IntPtr ptr)
|
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);
|
var wrapped = WrapEventPtr(ptr);
|
||||||
_del.Invoke(wrapped);
|
await _del.Invoke(wrapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EventData WrapEventPtr(IntPtr ptr)
|
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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using PkmnLibSharp.Battling;
|
using PkmnLibSharp.Battling;
|
||||||
using PkmnLibSharp.Battling.ChoiceTurn;
|
using PkmnLibSharp.Battling.ChoiceTurn;
|
||||||
|
@ -94,6 +95,7 @@ namespace PkmnLibSharpTests.Battling.BattleTests
|
||||||
battle.RegisterEventListener(new BattleEventListener(evt =>
|
battle.RegisterEventListener(new BattleEventListener(evt =>
|
||||||
{
|
{
|
||||||
evts.Add(evt);
|
evts.Add(evt);
|
||||||
|
return Task.CompletedTask;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
battle.SwitchPokemon(0, 0, p1.GetAtIndex(0));
|
battle.SwitchPokemon(0, 0, p1.GetAtIndex(0));
|
||||||
|
|
Loading…
Reference in New Issue