-
Notifications
You must be signed in to change notification settings - Fork 440
Improve handling of Lua script callbacks #4581
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
base: master
Are you sure you want to change the base?
Changes from all commits
75e6f68
b75184d
fd38382
be0b47b
1d88d33
4156f2d
c5565b6
a912e2e
7c9bec0
7d8f63f
3407d40
6d5b13f
cfe976b
13d75d9
7830f2e
32c8a62
f135c93
cfda77d
5d8228f
7790c71
1b5a5af
579f828
c3f27c9
0dd564b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,27 +4,29 @@ | |
| using System.Linq; | ||
| using System.Reflection; | ||
|
|
||
| using BizHawk.Client.Common; | ||
| using BizHawk.Emulation.Common; | ||
|
|
||
| namespace BizHawk.Client.EmuHawk | ||
| namespace BizHawk.Client.Common | ||
| { | ||
| public static class ApiManager | ||
| { | ||
| private static readonly IReadOnlyList<(Type ImplType, Type InterfaceType, ConstructorInfo Ctor, Type[] CtorTypes)> _apiTypes; | ||
| private static readonly List<(Type ImplType, Type InterfaceType, ConstructorInfo Ctor, Type[] CtorTypes)> _apiTypes = new(); | ||
|
|
||
| static ApiManager() | ||
| { | ||
| var list = new List<(Type, Type, ConstructorInfo, Type[])>(); | ||
| foreach (var implType in ReflectionCache_Biz_Cli_Com.Types.Concat(ReflectionCache.Types) | ||
| foreach (var implType in ReflectionCache_Biz_Cli_Com.Types | ||
| .Where(t => /*t.IsClass &&*/t.IsSealed)) // small optimisation; api impl. types are all sealed classes | ||
| { | ||
| var interfaceType = implType.GetInterfaces().FirstOrDefault(t => typeof(IExternalApi).IsAssignableFrom(t) && t != typeof(IExternalApi)); | ||
| if (interfaceType == null) continue; // if we couldn't determine what it's implementing, then it's not an api impl. type | ||
| var ctor = implType.GetConstructors().Single(); | ||
| list.Add((implType, interfaceType, ctor, ctor.GetParameters().Select(pi => pi.ParameterType).ToArray())); | ||
| AddApiType(implType); | ||
| } | ||
| _apiTypes = list.ToArray(); | ||
| } | ||
|
|
||
| public static void AddApiType(Type type) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't like this (used in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not affected by call order. The order of things in the list doesn't matter. And if it did matter, it would be an existing problem, not introduced in this PR. (Since the order given by ReflectionCache is not defined.) The only place it is called is in other static constructors. It is not mutated after static initialization. I do agree that this solution isn't ideal, but I do not think it's any worse than using reflection to find the types. Finding a good solution to this is outside the scope of this PR. EDIT: There was an issue here actually, with the static constructor not running. That has been fixed by moving it to |
||
| { | ||
| var interfaceType = type.GetInterfaces().FirstOrDefault(t => typeof(IExternalApi).IsAssignableFrom(t) && t != typeof(IExternalApi)); | ||
| if (interfaceType == null) return; // if we couldn't determine what it's implementing, then it's not an api impl. type | ||
| var ctor = type.GetConstructors().Single(); | ||
| _apiTypes.Add((type, interfaceType, ctor, ctor.GetParameters().Select(pi => pi.ParameterType).ToArray())); | ||
| } | ||
|
|
||
| private static ApiContainer? _container; | ||
|
|
@@ -38,7 +40,7 @@ private static ApiContainer Register( | |
| DisplayManagerBase displayManager, | ||
| InputManager inputManager, | ||
| IMovieSession movieSession, | ||
| ToolManager toolManager, | ||
| IToolLoader toolManager, | ||
| Config config, | ||
| IEmulator emulator, | ||
| IGameInfo game, | ||
|
|
@@ -52,7 +54,7 @@ private static ApiContainer Register( | |
| [typeof(DisplayManagerBase)] = displayManager, | ||
| [typeof(InputManager)] = inputManager, | ||
| [typeof(IMovieSession)] = movieSession, | ||
| [typeof(ToolManager)] = toolManager, | ||
| [typeof(IToolLoader)] = toolManager, | ||
| [typeof(Config)] = config, | ||
| [typeof(IEmulator)] = emulator, | ||
| [typeof(IGameInfo)] = game, | ||
|
|
@@ -74,7 +76,7 @@ public static IExternalApiProvider Restart( | |
| DisplayManagerBase displayManager, | ||
| InputManager inputManager, | ||
| IMovieSession movieSession, | ||
| ToolManager toolManager, | ||
| IToolLoader toolManager, | ||
| Config config, | ||
| IEmulator emulator, | ||
| IGameInfo game, | ||
|
|
@@ -92,7 +94,7 @@ public static ApiContainer RestartLua( | |
| DisplayManagerBase displayManager, | ||
| InputManager inputManager, | ||
| IMovieSession movieSession, | ||
| ToolManager toolManager, | ||
| IToolLoader toolManager, | ||
| Config config, | ||
| IEmulator emulator, | ||
| IGameInfo game, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| using BizHawk.Bizware.Graphics; | ||
| using BizHawk.Emulation.Common; | ||
|
|
||
| namespace BizHawk.Client.Common | ||
| { | ||
| public interface IMainFormForTools : IDialogController | ||
SuuperW marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| /// <remarks>referenced by 3 or more tools</remarks> | ||
| CheatCollection CheatList { get; } | ||
|
|
||
| /// <remarks>referenced by 3 or more tools</remarks> | ||
| string CurrentlyOpenRom { get; } | ||
|
|
||
| /// <remarks>referenced from HexEditor and RetroAchievements</remarks> | ||
| LoadRomArgs CurrentlyOpenRomArgs { get; } | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| bool EmulatorPaused { get; } | ||
|
|
||
| /// <remarks>only referenced from PlaybackBox</remarks> | ||
| bool HoldFrameAdvance { get; set; } | ||
|
|
||
| /// <remarks>only referenced from BasicBot</remarks> | ||
| bool InvisibleEmulation { get; set; } | ||
|
|
||
| /// <remarks>only referenced from LuaConsole</remarks> | ||
| bool IsTurboing { get; } | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| bool IsFastForwarding { get; } | ||
|
|
||
| /// <remarks>referenced from PlayMovie and TAStudio</remarks> | ||
| int? PauseOnFrame { get; set; } | ||
|
|
||
| /// <remarks>only referenced from PlaybackBox</remarks> | ||
| bool PressRewind { get; set; } | ||
|
|
||
| /// <remarks>referenced from BookmarksBranchesBox and VideoWriterChooserForm</remarks> | ||
| BitmapBuffer CaptureOSD(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| void DisableRewind(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| void EnableRewind(bool enabled); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| bool EnsureCoreIsAccurate(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| void FrameAdvance(bool discardApiHawkSurfaces = true); | ||
|
|
||
| /// <remarks>only referenced from LuaConsole</remarks> | ||
| /// <param name="forceWindowResize">Override <see cref="Common.Config.ResizeWithFramebuffer"/></param> | ||
| void FrameBufferResized(bool forceWindowResize = false); | ||
|
|
||
| /// <remarks>only referenced from BasicBot</remarks> | ||
| bool LoadQuickSave(int slot, bool suppressOSD = false); | ||
|
|
||
| /// <remarks>referenced from MultiDiskBundler and RetroAchievements</remarks> | ||
| bool LoadRom(string path, LoadRomArgs args); | ||
|
|
||
| /// <remarks>only referenced from BookmarksBranchesBox</remarks> | ||
| BitmapBuffer MakeScreenshotImage(); | ||
|
|
||
| /// <remarks>referenced from ToolFormBase</remarks> | ||
| void MaybePauseFromMenuOpened(); | ||
|
|
||
| /// <remarks>referenced from ToolFormBase</remarks> | ||
| void MaybeUnpauseFromMenuClosed(); | ||
|
|
||
| /// <remarks>referenced by 3 or more tools</remarks> | ||
| void PauseEmulator(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| bool BlockFrameAdvance { get; set; } | ||
|
|
||
| /// <remarks>referenced from PlaybackBox and TAStudio</remarks> | ||
| void SetMainformMovieInfo(); | ||
|
|
||
| /// <remarks>referenced by 3 or more tools</remarks> | ||
| bool StartNewMovie(IMovie movie, bool newMovie); | ||
|
|
||
| /// <remarks>only referenced from BasicBot</remarks> | ||
| void Throttle(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| void TogglePause(); | ||
|
|
||
| /// <remarks>referenced by 3 or more tools</remarks> | ||
| void UnpauseEmulator(); | ||
|
|
||
| /// <remarks>only referenced from BasicBot</remarks> | ||
| void Unthrottle(); | ||
|
|
||
| /// <remarks>only referenced from LogWindow</remarks> | ||
| void UpdateDumpInfo(RomStatus? newStatus = null); | ||
|
|
||
| /// <remarks>only referenced from BookmarksBranchesBox</remarks> | ||
| void UpdateStatusSlots(); | ||
|
|
||
| /// <remarks>only referenced from TAStudio</remarks> | ||
| void UpdateWindowTitle(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,8 @@ namespace BizHawk.Client.Common | |
| { | ||
| public interface ILuaLibraries | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this interface exist, again? b3c7f0f eliminated the multiple-implementations aspect, so is this just an abstraction to make it usable from Client.Common? I feel like we should be able to get rid of it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why should those callback properties stay? I do not see any value in keeping such callback logic in It could make sense to keep them if these two are combined, as a way of putting all the sets of I am not sure why |
||
| { | ||
| LuaFile CurrentFile { get; } | ||
|
|
||
| /// <remarks>pretty hacky... we don't want a lua script to be able to restart itself by rebooting the core</remarks> | ||
| bool IsRebootingCore { get; set; } | ||
|
|
||
|
|
@@ -13,5 +15,7 @@ public interface ILuaLibraries | |
| PathEntryCollection PathEntries { get; } | ||
|
|
||
| NLuaTableHelper GetTableHelper(); | ||
|
|
||
| void Sandbox(LuaFile luaFile, Action callback, Action<string> exceptionCallback = null); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,27 @@ | ||
| using BizHawk.Emulation.Common; | ||
|
|
||
| namespace BizHawk.Client.Common | ||
| { | ||
| public interface INamedLuaFunction | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, if
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not know. Looks like a good thing to remove to clean up the code. The git log shows you created the interface, and a quick look makes me think it was something to do with Unix/Win32 but I don't think that separation exists anymore. e4a0175 I will remove it if you think that's a good idea. |
||
| { | ||
| Action InputCallback { get; } | ||
|
|
||
| Guid Guid { get; } | ||
|
|
||
| string GuidStr { get; } | ||
|
|
||
| MemoryCallbackDelegate MemCallback { get; } | ||
|
|
||
| /// <summary>for <c>doom.on_prandom</c>; single param: caller of RNG, per categories <see href="https://github.com/TASEmulators/dsda-doom/blob/7f03360ce0e9000c394fb99869d78adf4603ade5/prboom2/src/m_random.h#L63-L133">in source</see></summary> | ||
| Action<int> RandomCallback { get; } | ||
|
|
||
| /// <summary>for <c>doom.on_use and doom.on_cross</c>; two params: pointers to activated line and to mobj that triggered it</summary> | ||
| Action<long, long> LineCallback { get; } | ||
|
|
||
| string Name { get; } | ||
|
|
||
| /// <summary> | ||
| /// Will be called when the Lua function is unregistered / removed from the list of active callbacks. | ||
| /// The intended use case is to support callback systems that don't directly support Lua. | ||
| /// Here's what that looks like: | ||
| /// 1) A NamedLuaFunction is created and added to it's owner's list of registered functions, as normal with all Lua functions. | ||
| /// 2) A C# function is created for this specific NamedLuaFunction, which calls the Lua function via <see cref="Call(object[])"/> and possibly does other related Lua setup and cleanup tasks. | ||
| /// 3) That C# function is added to the non-Lua callback system. | ||
| /// 4) <see cref="OnRemove"/> is assigned an <see cref="Action"/> that removes the C# function from the non-Lua callback. | ||
| /// </summary> | ||
| Action OnRemove { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Calls the Lua function with the given arguments. | ||
| /// </summary> | ||
| object[] Call(object[] args); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| namespace BizHawk.Client.Common | ||
| { | ||
| public interface IPrintingLibrary | ||
| { | ||
| void Log(params object[] outputs); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| namespace BizHawk.Client.Common | ||
| { | ||
| public interface IRegisterFunctions | ||
| { | ||
| LuaLibraryBase.NLFAddCallback CreateAndRegisterNamedFunction { get; set; } | ||
SuuperW marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree. I think the explicit type name is better.