• 🏆 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!

[Modules] StructUtils

Hey guys,

I have made a few little modules for basic struct stuff, such as save/loading, indexing and interval modules.

Dynamic$$Struct: You can create modules that stack actions.
This can be used to generate dynamic initializations/destroy methods that grow within modules.

SaveLoadStruct: Simple save/load module for storing the instances in a table.

IndexedStruct: Index and deindex stuff correctly.

PeriodicStruct: Using this you can run all instances methods every $period (static real of the struct) seconds.

JASS:
library StructUtils

    //! textmacro DynamicCallStructModule takes Action
    module Dynamic$Action$Struct
        public     static          trigger       $Action$Trigger = null
                
        public static method add$Action$ takes code theFunc returns triggeraction
            return TriggerAddAction(thistype.$Action$Trigger, theFunc)
        endmethod
        
        public static method remove$Action$ takes triggeraction theFunc returns nothing
            call TriggerRemoveAction(thistype.$Action$Trigger, theFunc)
        endmethod
        
        public static method invoke$Action$ takes nothing returns nothing
            call TriggerExecute(thistype.$Action$Trigger)
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.$Action$Trigger = CreateTrigger()
        endmethod
    endmodule
    //! endtextmacro
    
    //! runtextmacro DynamicCallStructModule("Create")
    //! runtextmacro DynamicCallStructModule("Register")
    //! runtextmacro DynamicCallStructModule("Periodic")
    //! runtextmacro DynamicCallStructModule("Cleanup")
    
    module SaveLoadStruct
        private     static      Table       INSTANCES   = 0
        public                  integer     id          = -1
        public      static      integer     SELF        = 0

        public method save takes nothing returns nothing
            set thistype.INSTANCES[.id] = integer(this)
        endmethod
        
        public method clear takes nothing returns nothing
            call thistype.INSTANCES.reset()
        endmethod
        
        public method remove takes nothing returns nothing
            call thistype.INSTANCES.flush(.id)
        endmethod
        
        public static method exists takes integer id returns boolean
            return thistype.INSTANCES.exists(id)
        endmethod
        
        public static method load takes integer id returns thistype
            return thistype(thistype.INSTANCES[id])
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.INSTANCES = Table.create()
        endmethod
    endmodule
    
    module IndexedStruct
        public      static      integer         amount          = 0
        
        implement SaveLoadStruct
        
        public method isIndexed takes nothing returns boolean
            return thistype.exists(.id)
        endmethod
        
        public static method lastKey takes nothing returns integer
            return thistype.amount -1
        endmethod
        
        public method index takes nothing returns boolean
            if .isIndexed() then
                return FALSE
            endif
            
            set .id = thistype.amount
            call .save()
            set thistype.amount = thistype.amount +1
            return TRUE
        endmethod
        
        public method deindex takes nothing returns boolean
            local thistype that = 0
        
            if not .isIndexed() then
                return FALSE
            endif
            
            call .remove()
            set thistype.amount = thistype.amount -1
            if thistype.amount >= 0 then
                set that = thistype.load(thistype.amount)
                if that != 0 then
                    call that.remove()
                    set that.id = .id
                    call that.save()
                endif
            endif
            return TRUE
        endmethod
    endmodule
    
    module PeriodicStruct
        public              boolean         isAlive         = FALSE
        public              boolean         isActive        = FALSE
        public  static      timer           clock           = null
        
        implement IndexedStruct
        
        public stub method onPeriod takes nothing returns boolean
            return TRUE
        endmethod
        
        public method isRegistered takes nothing returns boolean
            return .isIndexed()
        endmethod
        
        public method register takes nothing returns boolean
            if .index() then
                if thistype.lastKey() == 0 then
                    call thistype.startClock()
                endif
                return TRUE
            endif
            return FALSE
        endmethod
        
        public method unregister takes nothing returns boolean
            if .deindex() then
                if thistype.lastKey() == -1 then
                    call thistype.pauseClock()
                endif
                return TRUE
            endif
            return FALSE
        endmethod
                
        private static method runPeriod takes nothing returns nothing
            local integer i = 0
            local thistype this = 0
            
            loop
                exitwhen i > thistype.lastKey()
                                
                set this = thistype.load(i)
                set thistype.SELF = this
                
                if .onPeriod() then
                    set i = i +1
                else
                    call .destroy()
                endif
            endloop
        endmethod
        
        public static method startClock takes nothing returns nothing
            call TimerStart(thistype.clock, thistype.period, true, function thistype.runPeriod)
        endmethod
        
        public static method pauseClock takes nothing returns nothing
            call PauseTimer(thistype.clock)
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.clock = CreateTimer()
        endmethod
    endmodule
endlibrary

Simple example
JASS:
    struct Test

        implement IndexedStruct    
        
        // Add object to instances on creation
        public static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
    
            call .index()
            
            return this
        endmethod

        // and remove on destroy
        private method onDestroy takes nothing returns nothing
            call .deindex()
        endmethod

I hope it's useful enough to get approved.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Problem 1: combining 3 unrelated resources into one
Problem 2: there is indexing out there that is better than yours
Problem 3: there are already timer systems out there that are better than yours
Problem 4: there is already system out there better than your hashtable module
Problem 5: at the point you are going with triggers, it's better to just use triggers directly. Furthermore, it doesn't allow multiple triggers in 1 struct. At that point, it's just smarter to use Event.
 
Problem 1: combining 3 unrelated resources into one
Resource #2 needs #1 and 3 needs #2 and #1.

Problem 2: there is indexing out there that is better than yours
Show me? How can it be "better" if mine is small and effective?

Problem 3: there are already timer systems out there that are better than yours
Link please? I did not see anything like this that fits perfectly my intension.

Problem 4: there is already system out there better than your hashtable module
It's not a hashtable module, I forgot to tell that I used Vexorians Table library.

Problem 5: at the point you are going with triggers, it's better to just use triggers directly. Furthermore, it doesn't allow multiple triggers in 1 struct. At that point, it's just smarter to use Event.
Sorry, of course it's possible? All triggers have different names...
That's exaxctly what I am doing in my missile engine.
 
Top