Hello! After pouring through much of the ACT API documentation, I've determined that the data I need (Player data and stats, zone data, party data, etc.) for my plugin is within the FFXIV parser plugin object class. ACT does not seem to fire off an ActGlobals.oFormActMain.OnLogLineRead event for all LogLine types, only "0". This won't work for me, and I want to avoid the overhead of multiple log readers parsing the same log file as it's redundant and terribly inefficient. The FFXIV plugin does, however, have a public DataSubscriptions object that I can attach an event hook to the events I want to grab and circumvent this issue.
I realize I can iterate through the ActGlobals.oFormActMain.ActPlugins list and detect the parser, but trying to cast it from the simple IActPluginV1 interface to the actual class type exposed through the parser plugin assembly is causing a lot of headaches, since there's two separate assemblies (The ACT Assembly.LoadFrom/LoadFile and my referenced assembly type) and the types are not considered equal in that regard, even if sourced from the exact same DLL file, and an attempt to cast results in an InvalidCastException.
(See
https://docs.microsoft.com/en-us/dotnet/framework/deployment/best-practices-for-assembly-loading#avoid-loading-an-assembly-into-multiple-contexts for more information/further explanation on what's happening under the hood in this situation.)
What's the best method for gaining access to the class object instance? I'm sure someone has attempted this at some point.
Thanks in advance!
Edit: I want to add in that I do recognize that Ravahn may have seen this problem in advance and thus repeats most of the data via the "0" channel, however since it's made "human-readable", it becomes inefficient to parse that text when the raw parse log data is far preferable. I also expect that his "DataSubscription" class is intended for this purpose as well... but I have no way of reaching out to him to confirm.
Comments
That's an interesting problem actually. I'm not sure anyone has ever come to me for advice on such. I don't play FFXIV so I can't do exactly what you're doing... but it sounds simple enough to simulate based off of your description.
I will admit I was quite puzzled why it was inside of a byte array, but seeing your snippet explains a lot.
I would say if you ever fancy a refresh on the plugin code, I tend to agree with the best practices doc I previously linked, where it suggests the Add-In model that's provided by the Framework. (https://docs.microsoft.com/en-us/dotnet/framework/deployment/best-practices-for-assembly-loading#consider-using-the-net-framework-add-in-model), which takes away a lot of the busywork of managing assembly domains, security contexts, etc.
Also very interesting. I have only tiptoed into Ravahn's plug-in (by a subtle suggestion by him to disassemble his code, as he does not publish the source), and haven't quite pieced all the parts together.
Ultimately, to explain as briefly as possible, I'm trying to gain access to the memory-based dataset that he grabs from the running binary based off of known address offsets. This is where I would be able to get close to realtime player stats such as hit points, magic points, job, level, experience, etc. as it doesn't seem to come consistently through the log parsing method sourced from the network buffer that he also reads from. His plugin internally seems to keep a merged set of data within classes that I would love to get at to be able to read from.
What I really want to do is expose a full-set of game data in a common data format that external applications can hook to and get access to all the FFXIV data without needing to know anything about ACT, the XIV plugin, or the way XIV organizes it's data. This was inspired by trying to stream via OBS, and wanting real-time character stats available that aren't always visible or legible through the game screen capture.... in addition to all the combat stats that ACT produces. I thought if I could harness all that data and pipe it to an OBS plugin that's waiting for it, it would enable streamers to do some really cool things. But it seems that if I want more than combat stats, I'm going to have to hook up with the parsing add-ons to get the rest.
BTW, thanks for the quick responses!
They're all delegate functions, i.e.
...and he calls them whenever an event happens internally...
So I think it needs to be subscribed to first. For all I know it's an unfinished feature.
Interesting though, my code isn't so different than yours. Did you add a direct reference to the XIV DLL in the add-on project? I notice you're using the comment-reference technique you described in the coding tips section here, although not sure how that differs, especially at compile-time.
The rough code I was working with:
I'll keep tinkering around with it and see if I can't get past that exception and play around with it. If I get it working I'll let you know!
You said you were able to compile to a DLL and it loaded your test code fine?
Also, breaking into the debugger and inspecting the two object types, I see one is part of the ACT executable assembly, whereas the other is part of my add-on .DLL, which is why I'm probably getting the assembly base conflict that results in the Invalid Cast Exception, since .NET refuses to acknowledge two types are equal when they reside in different assembly domains. Otherwise both types are absolutely identical, even down to the GUID.
Since the plugin loading wasn't done with cross-plugin communication in-mind, and since the FFXIV plugin itself doesn't lend it's data out to anyone but ACT, unless you're willing to forfeit performance/reliability/data-halflife, I'm starting to think it's not feasible to attempt to gain game data access via ACT.
I thought of writing a parser that wrapped the FFXIV DLL, but that's asking for trouble.
I may have to resign myself to directly accessing the network buffer and memory blocks of FFXIV directly, alongside the FFXIV plugin. Ravahn does have another project he wrote that does have published source for reading the network data of FFXIV, and I can see the FFXIV plugin memory access code from the disassembly output. This gives me a head-start. And I can always use ACT's plugin interface for the actual combat performance statistics, which I do want.
This all being said, if you ever want a hand updating the plugin framework code, I'd certainly be willing to jump in. I think the current system would co-exist with a newer solution like the Add-In Framework. In fact, I believe all a plugin developer would need to do is attribute their main class that implements the IActPluginV1 interface to swap to that system. Most of the work is on the host side, and even then it's not much... and you gain a huge amount of reliability and flexibility.