Current ToDo

The latest version of the UOAI library and all directly related information can be found in this forum.

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 12:20 am

Ah k, you recompiled the source?

Cause the source is the old version, the binaries should be updated versions.

I'll update the source too, just forgot about that.

Edit: Actually it seems like the binaries weren't updated correctly neither, I'll attach the updated version in a minute.
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby arul on Mon Nov 24, 2008 12:27 am

EDIT: Cool, thanks.

Nah, I didn't recompile the source :)

Here's the code I tried:

Code: Select all
      static void Main( string[] args )
      {
         UOAIClass cls = new UOAIClass();

         foreach( UOClient c in cls.Clients )
         {
            Debug.WriteLine("Hooking: " + c.Player.Name);
            c.onPacketReceive+=new UOClientCallbackVtbl_onPacketReceiveEventHandler( c_onPacketReceive );
         }

         Console.ReadLine();
      }

      static void c_onPacketReceive( ref Array packet, int packetsize )
      {
         Debug.WriteLine( "Packet received" );
      }


The message 'Hooking: playerName' shows up, but "Packet received" doesn't :/
arul
Pro
 
Posts: 107
Joined: Thu Nov 20, 2008 2:03 am
Location: Prague

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 12:35 am

Should work just fine with the updated version, attached to this post.

Update: seems to work from vb6, not yet from C#... will look into it.
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 1:04 am

I'm off to bed, got to get up early tomorrow.

Didn't get it to work in C# yet even though it seems to trigger the events fine in vb6, I will look into it when I find the time tomorrow.

Let me know if you find the problem.

Greetz,
Artaxerxes
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby arul on Mon Nov 24, 2008 2:11 am

DISP_E_MEMBERNOTFOUND - The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.


This is the HRESULT I get after executing this method:

Code: Select all
      hr = outgoingdispinterface->lpVtbl->Invoke(outgoingdispinterface,toinvoke,&IID_NULL,0,DISPATCH_METHOD,parameterlist,0,0,&argerror);


argerror in this case is 0xFFFFFFFF.

I tried googling for some clues but found nothing.
arul
Pro
 
Posts: 107
Joined: Thu Nov 20, 2008 2:03 am
Location: Prague

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 2:37 am

I couldnt sleep until I figured it out. :D

Got to that same HRESULT too...

The problem seems to be that C# does not generate the CallbackInterfaces correctly, in that it does not stick to the DISPIDs I assign to my functions in my typelibrary. Maybe there is some info it requires missing in my typelib, I'm not sure yet.

However, I can currently solve it by querying the dispids at runtime. I ran a test for one eventhandler, and it works fine. I'll add the required code to make it work for all handlers tomorrow... now: off to bed :).

Greetz,
Artaxerxes
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby arul on Mon Nov 24, 2008 3:01 am

Artaxerxes wrote:I couldnt sleep until I figured it out. :D

Got to that same HRESULT too...

The problem seems to be that C# does not generate the CallbackInterfaces correctly, in that it does not stick to the DISPIDs I assign to my functions in my typelibrary. Maybe there is some info it requires missing in my typelib, I'm not sure yet.

However, I can currently solve it by querying the dispids at runtime. I ran a test for one eventhandler, and it works fine. I'll add the required code to make it work for all handlers tomorrow... now: off to bed :).

Greetz,
Artaxerxes


Excellent, good job :)

Could you also please elaborate on what you changed to make it work? I've been reading a lot of about COM lately and would like to know where was the culprit, just out of curiosity :)
arul
Pro
 
Posts: 107
Joined: Thu Nov 20, 2008 2:03 am
Location: Prague

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 8:22 am

Well... don't know how much you read already, but In COM events work sort of like this: my app defines and declares a class (actually an interface definition, not a class) in its typelibrary (for each object that has events), without implementing it. The member-function of such a 'class' have the prototype of the events I'd like to expose. An app that wants to get those events, must provide an implementation for that class and hand me a (pointer to) an object instance of that class. So instead of getting function pointers, I get an object, with its members being the events to trigger. So all my app has to do is call those member functions. Now that might sound simple, but in fact, since UOAI and your program implementing the event-object might be two different applications, "calling" the member on the object you passed me, means I'm calling a function in another app. Now, that is actually what COM does for me: it sets up a duplicate object in my program, with memberfunctions that will call the remote object's corresponding members through Inter Process Communication (mostly through windows messages). However, for scripting languages another facility is provided: calls can be made through the IDispatch interface. If every interface in my app is derived from IDispatch (has its first member-functions the same as IDispatch) then a scripting language can call all members through IDispatch and does not have to know all other members. This is convenient, since f.e. if I call UOAI.LaunchClient in vbScript, then vbScript has no idea at what offset LaunchClient is in my interface, so it cant call it directly. VbScript then simply assumes that the UOAI class (interface) starts with IDispatch-functions, of which it does know the offsets, and simply calls: IDispatch.GetIDsOfNames(... "LaunchClient" ) which looks up an ID (dispid) for the "LaunchClient" method and then it can call that method through IDispatch.Invoke( ... dispid ... ).
Now, in visual basic 6, that's also the only way that events are supported: vb generates an object for me sticking to the event-class (interface) I defined, but it only supports calls through the IDispatch methods, not direct access to all members. So when triggering an event I have to call those members on the remote object by calling its IDispatch.Invoke(...event's dispid...). For performance reasons, instead of looking up that dispID each time (which requires text-comparisons and thus is slow), I predefine the DispIDs for the members in my typelibrary (which Visual Basic can read). So I have f.e. member-function with ID 0 on the UOAICallback class (interface) is the OnClientStart event, so if a client is detected and my program has an eventobject of that class (which it will if your application setup eventhandlers) then it will call eventobject.Invoke(... ID: 0 ...).
The problem is that even though C# sets up the eventobject correctly and passes it to my app successfully, the member-functions in the eventobject I got from C# does not use the right DISPIDs. So, even though visual basic seems to use the correct DISPIDs, it seems like some information is missing in my typelibrary to tell C# that those DISPIDs have to be used.
Now, I can solve this by calling the IDispatch.GetIDsOfNames(...) function, looking up the dispids C# uses, instead of using the predefined dispids. This will require text-lookup, so a performance loss, but if I can do this at the point where i get the eventobject (so each time you do "UOAI.onClientStart+=new ...delegate...(eventhandler_func);"), I would minimize performance issues (compared to looking up the dispid each time I invoke the event).
I think, however, that I know what information is missing in my typelibrary: i think the event-interfaces (classes) have to be marked with the "oleautomation" attribute to get C# to set-up the IDispatch-interface correctly (including the correct DISPIDs), but I haven't tried that yet.

Sorry for the extremely long post... I hope it was clear in some way, if not plz ask!
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby Artaxerxes on Mon Nov 24, 2008 5:18 pm

Ok, I think I fixed the problems with C#<->Com-events compatiblity.

In attachment to this post is a version that should trigger the following events succesfully:
  • UOAI.onClientStart(UOClient newclient)
  • UOAI.onClientExit(UOClient invalidclient)
  • UOClient.onPacketReceive(Byte[] packet, int packetsize)
  • UOClient.onPacketSend(Byte[] packet, int packetsize)
  • UOClient.onExit()
  • UOClient.onNewItem(UOItem newitem)
  • UOClient.onNewMobile(UOMobile newmobile)
  • UOClient.onKeyDown(int virtualkeycode)
  • UOClient.onKeyUp(int virtualkeycode)

Greetz,
Artaxerxes
Attachments
UOAISetup.rar
(210.04 KiB) Downloaded 18 times
Artaxerxes
Site Admin
 
Posts: 530
Joined: Tue Nov 18, 2008 9:51 pm

Re: Current ToDo

Postby Carpates on Mon Nov 24, 2008 6:13 pm

Very nice job with the event handling. Any chance we can get an onMobileExit, i.e. when a Mobile leaves the field of view? By the way, a small annoyance: 'targetting' vs. 'targeting.'
Carpates
Coder
 
Posts: 12
Joined: Mon Nov 24, 2008 9:45 am
Location: Germany

PreviousNext

Return to UOAI Developers Forum

Who is online

Users browsing this forum: No registered users and 1 guest

cron