• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] Passing variables through 2 libraries, usage of stub methods and other things

Status
Not open for further replies.
Level 25
Joined
Jun 5, 2008
Messages
2,572
So i have an issue which has thrown me into a thinking for far too many times.

I have a system which i had lying around for some time, i decided to start rewriting it.

Now i wanted to keep it modular and to separate the parts of the data structure, data manipulation and data rendering.

And so we come to my problem, i need two variables (a x and y coordinate) to be passable between two libraries only but is inside a global block of one.
Example:
JASS:
library One
 globals
   private constant real x = 10.0
   private constant real y = 2.0
 endglobals
endlibrary

Is there any way without making them non-private or merging the two libraries to pass these 2 variables to library Two for example?

The other thing:
I have several simmilar data structures so i resorted to using an interface extended via structs.
Now in order to have more readability and cleaner code i wanted to implement a static operator:
JASS:
static method operator [] takes integer i returns thistype
 local thistype this = LoadInteger(SomeHashtable, i, someKey)
 return this
endmethod

But as operators aren't allowed in interfaces (or at least i couldn't get them to work) i used the following structure:
JASS:
struct a
 integer b
 integer c
 
 static method operator [] takes integer i returns thistype
     local thistype this = LoadInteger(SomeHashtable, i, someKey)
     return this
 endmethod

 stub method firstAction takes nothing returns nothing
 endmethod
endstruct

struct one extends a
 
 method firstAction takes nothing returns nothing
  set b = 1 //example ofc, not this trivial.
 endmethod
endstruct

So any ideas on a better structure?
I read that stub methods are almost never used, so i would like to hear of a different aproach.
And i hope the usage of the operator is okay in this case.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
Let's see if this sheds more light, the stub methods are actually functions that are called on trigger events.

The following code would for example be called upon firing an event and passing the condition:
JASS:
struct a
 integer b
 integer c
 
 static method operator [] takes integer i returns thistype
     local thistype this = LoadInteger(SomeHashtable, i, someKey)
     return this
 endmethod

 stub method firstAction takes nothing returns nothing
 endmethod
endstruct

struct one extends a
 
 method firstAction takes nothing returns nothing
  set b = 1 //example ofc, not this trivial.
 endmethod
endstruct

struct two extends a

 method firstAction takes nothing returns nothing
  set c = 12
 endmethod

endstruct


private function eventFire takes nothing returns nothing
 local struct a = LoadInteger(SomeHashtable, GetHandleId(something), somenumber)
 call a.firstAction()
endfunction

Being as we do not know the type of the struct that is extending it (one, two, etc) i am adressing the extended struct.

I asume this is the correct usage?
Edit:

The reason i want the operator is for me to be able to use for example:
JASS:
local struct a = a[GetHandleId(something)]

Instead of writing load integer over and over.

Edit2:

Would this be a better solution? Taken from jass helper documentation:
JASS:
interface myinterface
   method processunit takes unit u returns nothing
   method onAnEvent takes nothing returns boolean
endinterface

struct A extends myinterface

   method processunit takes unit u returns nothing
       call KillUnit(u)
   endmethod

   method onAnEvent takes nothing returns boolean
       return false
   endmethod
endstruct

struct B extends A

   method processunit takes unit u returns nothing
      //we have just replaced A's processunit method,
      //if an interface variable of type myinterface holds an instance of 
      //type B it will explode the unit.
      call ExplodeUnitBJ(u)
   endmethod
   // we are implementing processunit but we do not have to implement onAnEvent   

endstruct

No stub methods but i personally never used this aproach.
 
Last edited:
Ah, that's what you wanted to do.
Use a module.

JASS:
module DataHandler
    static method operator [] takes integer i returns thistype
        // blabla
    endmethod

    static method operator []= takes integer i, integer j returns nothing
        // blabla
    endmethod
endmodule

struct A extends array
    implement DataHandler
endstruct

struct B extends array
    implement DataHandler
endstruct

struct C extends array
    implement DataHandler
endstruct

struct D extends array
    implement DataHandler
endstruct
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
But... that doesn't make sense.

I can't implement modules into an interface and i don't know which struct type i need to access (struct A, struct B, struct C) that is why i am refrencing the struct that is extended (in my case struct a).

And the parent needs to have firstAction function because it is called like i mentioned:
JASS:
private function eventFire takes nothing returns nothing
 local struct a = LoadInteger(SomeHashtable, GetHandleId(something), somenumber)
 call a.firstAction()
endfunction

^ in that trigger it is unkown if the firstAction will be from struct one or struct two.

Edit:

Okay let me post some of the code here:
JASS:
    private struct   iTrack
    
        real        x
        real        y
        integer     count
        integer     playerId
        trackable   t
    
        static  trigger TrackEvent = CreateTrigger()
        static  trigger HitEvent = CreateTrigger()
        
        static  method  operator    [] takes trackable t returns thistype
            local thistype this = LoadInteger(sometable, Key, GetHandleId(t))
            return this
        endmethod
        
        stub method onTrack takes nothing returns nothing
        endmethod
        
        stub method onHit takes nothing returns nothing
        endmethod
        
    
    endstruct

   struct a extends iTrack
              private method onTrack takes nothing returns nothing
                  // some actions
              endmethod
   endstruct

   struct b extends iTrack
              private method onTrack takes nothing returns nothing
                  // some actions
              endmethod
   endstruct


   // i do not know if struct a or b is going to get loaded through the hashtable, i thus use the iTrack.onTrack(), all trackables are registered to iTrack.TrackEvent trigger, depending on the trackable type i do the track actions accompanied by them.

    private function Track takes nothing returns boolean
        local iTrack dat = iTrack[GetTriggeringTrackable()]
        if dat.t == null then
            return false
        endif
        call dat.onTrack()
        return false
    endfunction
 
Last edited:
Level 25
Joined
Jun 5, 2008
Messages
2,572
I am open to all alternatives which would provide the same functionality.
That is the reason of creating this thread afterall, i know this way works but wanted to know if there are alternative ways and if so which.

If you could provide an example of what you mean by lower level DSG that would be great.
 
I normally just use a simple register function.
JASS:
globals
    trigger registerTrigger = CreateTrigger()
endglobals

function RegisterEvent takes code c returns nothing
    call TriggerAddCondition(registerTrigger, Filter(c))
endfunction

function FireEvent takes nothing returns nothing
    call TriggerEvaluate(registerTrigger)
endfunction

If you understand what I mean. I assume you are trying to make psuedo events so that the methods you want run on trackable tracks and clicks. That is the method I would choose.

I don't think you can do what you are attempting to do with just stub methods. They can rewrite methods when you have a struct that extends a parent struct, but you still have to call the child struct's method explicitly. Calling the parent struct's method won't fire all the other methods.

You can also use function interfaces, but they are essentially the same thing. Check out this system to see how you can use it to fire events:
http://www.wc3c.net/showthread.php?t=108009
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
I want to be able to call iTrack.onTrack() (the parent struct) and not know which of the child's method i am actually calling (struct a or b).

They are all registered to one event and when you hold your mouse over 1 trackable type it should do different things than when holding it over another trackable type.
I guess i could save the method to the handle of the trackable and call it via that, that is a interesting new idea.

Like:

JASS:
private struct   iTrack
 
     real        x
     real        y
     integer     count
     integer     playerId
     trackable   t
     code      c
 
     static  trigger TrackEvent = CreateTrigger()
     static  trigger HitEvent = CreateTrigger()
     
     static  method  operator    [] takes trackable t returns thistype
         local thistype this = LoadInteger(sometable, Key, GetHandleId(t))
         return this
     endmethod
     
     
 
 endstruct

struct a extends iTrack
           private method onTrack takes nothing returns nothing
               // some actions
           endmethod
endstruct

struct b extends iTrack
           private method onTrack takes nothing returns nothing
               // some actions
           endmethod
endstruct


// i do not know if struct a or b is going to get loaded through the hashtable, i thus use the iTrack.onTrack(), all trackables are registered to iTrack.TrackEvent trigger, depending on the trackable type i do the track actions accompanied by them.

 private function Track takes nothing returns boolean
     local iTrack dat = iTrack[GetTriggeringTrackable()]
     if dat.t == null then
         return false
     endif
     call dat.c()
     return false
 endfunction

Where c would point to onTrack methods of the child structs.
How about that then?
 
You would use a module.

JASS:
library iTrackSystem

    globals
        private trigger systemTrigger = CreateTrigger()
    endglobals

    struct iTrack extends array
        // bla bla bla
    endstruct

    function GetTriggeringTrackInstance takes nothing returns iTrack
        return something
    endfunction

    module iTrackStruct

        private static method onTrackProx takes nothing returns nothing
            call thistype(GetTriggeringTrackInstance()).onTrack()
        endmethod
        
        private static method onInit takes nothing returns nothing
            static if thistype.onTrack.exists then
                call TriggerAddCondition(systemTrigger, Condition(function thistype.onTrackProx))
            endif
        endmethod
    endmodule
endlibrary

You would implement that module into the structs you want.

Whenever a trackable is hit or something, you would store the instance internally in your system so that GetTriggeringTrackInstance returns that instance.

You would then do this:
call TriggerEvaluate(systemTrigger)

And all the onTrack methods will fire.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
And all the onTrack methods will fire.
I am confused by this.
Why would i want all the methods to fire?

There is 1 method per trackable, only difference is which method depending on what struct is bound to the trackable.

Whenever a trackable is hit or something, you would store the instance internally in your system

I am asuming this means the thing i had in mind:
During the creation of the structs that extend the iTrack a instance of that struct is saved to the handle of the trackable using hashtable.

Then when the trackable is tracked, the instance is loaded and it's onTrack method should be fired.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
Sorry for double post, just wanted to say the issue has been resolved.
I resolved to using:
JASS:
    private interface   I
    
        real        x
        real        y
        integer     count
        integer     playerId
        trackable   t
    
        static  trigger TrackEvent = CreateTrigger()
        static  trigger HitEvent = CreateTrigger()
        
        method onTrack takes nothing returns nothing defaults nothing
        method onHit takes nothing returns nothing defaults nothing
    
    endinterface

    private struct   iTrack extends I
    
        static method operator [] takes trackable t returns thistype
            local thistype this = LoadInteger(customInventory.table, customInventory.trackableKey, GetHandleId(t))
            return this
        endmethod
        
        static method operator []= takes trackable t, integer i returns nothing
            call SaveInteger(customInventory.table, customInventory.trackableKey, GetHandleId(t), i)
        endmethod
        
    endstruct

    private struct a extends iTrack

        private method onHit takes nothing returns nothing
            call BJDebugMsg("hit a")
        endmethod
        
        private method onTrack takes nothing returns nothing
            call BJDebugMsg("tracked a")
        endmethod

    endstruct

    private struct b extends iTrack

        private method onHit takes nothing returns nothing
            call BJDebugMsg("hit b")
        endmethod
        
        private method onTrack takes nothing returns nothing
            call BJDebugMsg("tracked b")
        endmethod

    endstruct

     private function Track takes nothing returns boolean
        local iTrack dat = iTrack[GetTriggeringTrackable()]
        if dat.t == null then
            return false
        endif
        call dat.onTrack()
        return false
    endfunction
    
    private function Hit takes nothing returns boolean
        local iTrack dat = iTrack[GetTriggeringTrackable()]
        if dat.t == null then
            return false
        endif
        call dat.onHit()
        return false
    endfunction
 
Status
Not open for further replies.
Top